Перевести готовый код (преобразование списка словарей ) с Python на Typescript

Есть входные данные в виде списка словарей. Надо:

  1. в каждом словаре вытащить значение по одному из ключей
  2. разбить его по пробелу и взять первую половину
  3. сделать новый пустой словарь
  4. строку из п.2 сделать ключом, а значением стартовый словарь из п. 1.

Проще показать, чем объяснять.

Входящие данные.

slots = [
      {'qwe': "qwevrtyu", 'asd': "hdf dfgfg", 'zxc': "fjfjwvb"},
      {'qwe': "qxcvtyu", 'asd': "hdf mkvfg", 'zxc': "kdkd[vb"},
      {'qwe': "bnmrtyu", 'asd': "hdf hskfyweee", 'zxc': "jfjfjfjfb"},
      {'qwe': "zxcvtyu", 'asd': "ahfh fhfhf", 'zxc': "lflflflf"},
      {'qwe': "qwerbnm", 'asd': "ahfh sgfdhfovppd", 'zxc': "lflflflffff"},
      {'qwe': "qwnm", 'asd': "ahfh hfovppd", 'zxc': "lfdddfff"},
      {'qwe': "qwerbnm", 'asd': "sgfd dessppd", 'zxc': "lflflflffff"},
      {'qwe': "qwerbnm", 'asd': "sgfd qweerpd", 'zxc': "lflflflffff"},
      {'qwe': "qwerbnm", 'asd': "sgfd kfkfkfd", 'zxc': "lflflflffff"}
    ]

Выходящие данные.

[
{'hdf':
[{'qwe': 'qwevrtyu', 'asd': 'hdf dfgfg', 'zxc': 'fjfjwvb'},
{'qwe': 'qxcvtyu', 'asd': 'hdf mkvfg', 'zxc': 'kdkd[vb'},
{'qwe': 'bnmrtyu', 'asd': 'hdf hskfyweee', 'zxc': 'jfjfjfjfb'}]},

{'ahfh':
[{'qwe': 'zxcvtyu', 'asd': 'ahfh fhfhf', 'zxc': 'lflflflf'},
{'qwe': 'qwerbnm', 'asd': 'ahfh sgfdhfovppd', 'zxc': 'lflflflffff'},
{'qwe': 'qwnm', 'asd': 'ahfh hfovppd', 'zxc': 'lfdddfff'}]},

{'sgfd':
[{'qwe': 'qwerbnm', 'asd': 'sgfd dessppd', 'zxc': 'lflflflffff'},
{'qwe': 'qwerbnm', 'asd': 'sgfd qweerpd', 'zxc': 'lflflflffff'},
{'qwe': 'qwerbnm', 'asd': 'sgfd kfkfkfd', 'zxc': 'lflflflffff'}]}
]

Код на Python, работает корректно.

def processSlots(data):
    result = []
    keys_list = []
    for slot in data:
        elem_key = slot['asd'].split(" ")[0]
        if elem_key in keys_list:
            for my_dict in result:
                try:
                    my_dict[elem_key].append(slot)
                except KeyError:     
                    pass
        else:
            my_dict = {}
            elem_value = []
            my_dict[elem_key] = elem_value
            elem_value.append(slot)
            result.append(my_dict)
            keys_list.append(elem_key)
    return [result, keys_list]

Теперь самое главное - надо этот работающий код на Питоне перевести на Typescript. Сделано на ~90%, но на оставшихся 10 % я застрял.

export interface Slot {
    qwe: string;
    asd: string;
    zxc: string;
}


const processSlots = (data: Array<Slot>) => {
    interface my_dict_interface {
        [key: string]: Array<Slot>            
    };
    const result: Array<my_dict_interface> = [];     
    const keys_list: string[] = [];            
    for (let i = 0; i < data.length; i++) {
        const slot: Slot = data[i];
        const elem_key: string = slot['asd'].split(" ")[0];
        let my_dict: my_dict_interface;
        if (elem_key in keys_list) {
            for (const my_dict in result) {
                try {
                    my_dict[elem_key].add(slot);    //Element implicitly has an 'any' type because index expression is not of type 'number'.
                }
                catch (e: unknown) {
                    console.log("...ups, i did it again ", e)
                }
            }
        }
        else {
            const elem_value: Slot[] = []
            my_dict[elem_key] = elem_value;          // Variable 'my_dict' is used before being assigned.
            elem_value.push(slot);
            result.push(my_dict);                     // Variable 'my_dict' is used before being assigned.
            keys_list.push(elem_key);
        }
    }  
    return [result, keys_list]; 
}

Выходящие данные должны быть как в примере с Питоном, ну это понятно.


Ответы (3 шт):

Автор решения: SVBazuev

Я бы делал иначе.

Cложность O(n^2), где n — количество объектов в массиве slots
Python:

import re


unique_prefixes = set(re.match(r'(\S+)', item['asd']).group(0) for item in slots)
print(unique_prefixes)  # {'hdf', 'ahfh', 'sgfd'}


result = {
    pref: [item for item in slots if item['asd'].startswith(f'{pref} ')]
    for pref in  unique_prefixes
}

JavaScript:

const slots = [
    { 'qwe': "qwevrtyu", 'asd': "hdf dfgfg", 'zxc': "fjfjwvb" },
    { 'qwe': "qxcvtyu", 'asd': "hdf mkvfg", 'zxc': "kdkd[vb" },
    { 'qwe': "bnmrtyu", 'asd': "hdf hskfyweee", 'zxc': "jfjfjfjfb" },
    { 'qwe': "zxcvtyu", 'asd': "ahfh fhfhf", 'zxc': "lflflflf" },
    { 'qwe': "qwerbnm", 'asd': "ahfh sgfdhfovppd", 'zxc': "lflflflffff" },
    { 'qwe': "qwnm", 'asd': "ahfh hfovppd", 'zxc': "lfdddfff" },
    { 'qwe': "qwerbnm", 'asd': "sgfd dessppd", 'zxc': "lflflflffff" },
    { 'qwe': "qwerbnm", 'asd': "sgfd qweerpd", 'zxc': "lflflflffff" },
    { 'qwe': "qwerbnm", 'asd': "sgfd kfkfkfd", 'zxc': "lflflflffff" }
];

const uniquePrefixes = new Set(slots.map(item => item.asd.split(' ')[0]));

const result = {};
uniquePrefixes.forEach(prefix => {
    result[prefix] = slots.filter(item => item.asd.startsWith(`${prefix} `));
});

console.log(result);



UPD: оптимизация, сложность O(n),
где n — количество объектов в массиве slots

Python:

import re

result = {}
for item in slots:
    if match := re.match(r'(\S+)', item['asd']):
        if (prefix := match.group(0)) not in result:
            result[prefix] = []
        result[prefix].append(item)

JavaScript:

const slots = [
    { 'qwe': "qwevrtyu", 'asd': "hdf dfgfg", 'zxc': "fjfjwvb" },
    { 'qwe': "qxcvtyu", 'asd': "hdf mkvfg", 'zxc': "kdkd[vb" },
    { 'qwe': "bnmrtyu", 'asd': "hdf hskfyweee", 'zxc': "jfjfjfjfb" },
    { 'qwe': "zxcvtyu", 'asd': "ahfh fhfhf", 'zxc': "lflflflf" },
    { 'qwe': "qwerbnm", 'asd': "ahfh sgfdhfovppd", 'zxc': "lflflflffff" },
    { 'qwe': "qwnm", 'asd': "ahfh hfovppd", 'zxc': "lfdddfff" },
    { 'qwe': "qwerbnm", 'asd': "sgfd dessppd", 'zxc': "lflflflffff" },
    { 'qwe': "qwerbnm", 'asd': "sgfd qweerpd", 'zxc': "lflflflffff" },
    { 'qwe': "qwerbnm", 'asd': "sgfd kfkfkfd", 'zxc': "lflflflffff" }
];

const result = {};

slots.forEach(item => {
    const prefix = item.asd.split(' ')[0];
    if (!result[prefix]) {
        result[prefix] = [];
    }
    result[prefix].push(item);
});

console.log(result);


Ну а в TypeScript, Вы сами это реализуете...

Успехов!

→ Ссылка
Автор решения: Stanislav Volodarskiy

Исходный код выдаёт список словарей вместо одного словаря, что противоречит постановке задачи.

Перебираем слоты, для каждого слота вычисляем ключ, если ключа нет, добавляем его в результат, добавляем слот в массив значений:

interface Slot {
    qwe: string;
    asd: string;
    zxc: string;
}

interface Result {
    [key: string]: Array<Slot>            
}

const processSlots = (slots: Array<Slot>): Result => {
    const d: Result = {};
    for (const slot of slots) {
        const asd = slot.asd;
        const key = asd.slice(0, asd.indexOf(' '));  // вычисление ключа
        if (!Object.hasOwn(key, d)) {                // добавляем ключ в результат
            d[key] = [];
        }
        d[key].push(slot);                           // добавляем слот в массив
    }
    return d;
};
→ Ссылка
Автор решения: Qwertiy

var slots = [
  {'qwe': "qwevrtyu", 'asd': "hdf dfgfg", 'zxc': "fjfjwvb"},
  {'qwe': "qxcvtyu", 'asd': "hdf mkvfg", 'zxc': "kdkd[vb"},
  {'qwe': "bnmrtyu", 'asd': "hdf hskfyweee", 'zxc': "jfjfjfjfb"},
  {'qwe': "zxcvtyu", 'asd': "ahfh fhfhf", 'zxc': "lflflflf"},
  {'qwe': "qwerbnm", 'asd': "ahfh sgfdhfovppd", 'zxc': "lflflflffff"},
  {'qwe': "qwnm", 'asd': "ahfh hfovppd", 'zxc': "lfdddfff"},
  {'qwe': "qwerbnm", 'asd': "sgfd dessppd", 'zxc': "lflflflffff"},
  {'qwe': "qwerbnm", 'asd': "sgfd qweerpd", 'zxc': "lflflflffff"},
  {'qwe': "qwerbnm", 'asd': "sgfd kfkfkfd", 'zxc': "lflflflffff"}
]

var res = Object.create(null)

for (var x of slots) {
  (res[x.asd.split(" ")[0]] ||= []).push(x)
}

console.log(res)
.as-console-wrapper.as-console-wrapper {
  max-height: 100vh;
}

На ts почти так же: playground

var slots: ({ [key in string]?: string } & { asd: string })[] = [
    {'qwe': "qwevrtyu", 'asd': "hdf dfgfg", 'zxc': "fjfjwvb"},
    {'qwe': "qxcvtyu", 'asd': "hdf mkvfg", 'zxc': "kdkd[vb"},
    {'qwe': "bnmrtyu", 'asd': "hdf hskfyweee", 'zxc': "jfjfjfjfb"},
    {'qwe': "zxcvtyu", 'asd': "ahfh fhfhf", 'zxc': "lflflflf"},
    {'qwe': "qwerbnm", 'asd': "ahfh sgfdhfovppd", 'zxc': "lflflflffff"},
    {'qwe': "qwnm", 'asd': "ahfh hfovppd", 'zxc': "lfdddfff"},
    {'qwe': "qwerbnm", 'asd': "sgfd dessppd", 'zxc': "lflflflffff"},
    {'qwe': "qwerbnm", 'asd': "sgfd qweerpd", 'zxc': "lflflflffff"},
    {'qwe': "qwerbnm", 'asd': "sgfd kfkfkfd", 'zxc': "lflflflffff"}
]

var res: { [key in string]?: (typeof slots)[number][] } = Object.create(null)

for (var x of slots) {
    (res[x.asd.split(" ")[0]] ||= []).push(x)
}

console.log(res)
→ Ссылка