Наиболее эффективный способ переупорядочения списка объектов с использованием свойства order, которое есть у каждого объекта - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь создать алгоритм, который будет проходить через список объектов и сортировать их, но не точно сортировать, как перемещение элементов списка на основе свойства, порядок исходного списка не изменяется , порядок определяет не то, как объекты сортируются внутри списка, а свойство, которое каждый объект назвал order, которое является целым числом.

Чтобы сделать его немного сложнее, это переупорядочение выполняется на основе другого списка, называемого здесь reorderer_list, который содержит словари, представляющие объекты, со всеми их свойствами, включая order, но они просто сортируются в правильный порядок внутри этого reorderer_list (их свойства order также могут быть неправильными)

В основном, пример ситуации будет:

reorderer_list = [{"order": 7, "name": "Tom"}, {"order": 5, "name": "Sara"}, {"order": 6, "name": "John"}]

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

[{"order": 5, "name": "Tom"}, {"order": 6, "name": "Sara"}, {"order": 7, "name": "John"}]

или

[{"order": 6, "name": "Sara"}, {"order": 7, "name": "John"}, {"order": 5, "name": "Tom"}]

не имеет значения, оба являются правильными (они оба являются правильными, потому что сортировка элементов внутри окончательного списка не имеет значения, какое значение имеет only свойство order, я просто использовал это пример для объяснения этого. Исходный список будет содержать эти три имени (например), отсортированные в любом порядке внутри списка с любым значением для order, это не имеет значения, в конце должно быть свойство исходного списка order организован так, чтобы соответствовать фактической сортировке reorderer_list элементов внутри него.

Также важно заметить, что иногда исходный список и переупорядоченный список могут иметь разный размер, объекты, у которых изменилась позиция, всегда будут существовать в обоих списках

Вот что я уже пробовал: list_data - исходный список, reorderer_list - новый список с правильным порядком

# This will find the differences between the reordered list and the original list
changedOrderItems = []
changedOrderItemsOrders = []
for index, product in enumerate(list_data):
    #Sizes may be different, avoid IndexError
    if index == len(reorderer_list):
        break
    # Is different
    if product.name != reorderer_list[index]["name"]:
        #Append to temporary list, the items from reorderer list
        changedOrderItems.append(reorderer_list[index])
        #Append to temporary list, the order property of these items
        changedOrderItemsOrders.append(reorderer_list[index]["order"])

#Sort the orders list
changedOrderItemsOrders.sort()

# Cycles through the temporary list and finds the index of the respective object in the original list and sets it's order number according to the sorted changedOrderItemsOrders list
for i, item in enumerate(changedOrderItems):
    from_data_index = next((index for (index, d) in enumerate(list_data) if d.name == item["name"]), None)

    list_data[from_data_index].order = changedOrderItemsOrders[i]

Это работает, но я хочу знать, есть ли способы улучшить этот беспорядок?

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

IIUC вот что ОП хочет:

initial_list = [{"order": 5, "name": "Sara"}, {"order": 6, "name": "John"}, {"order": 7, "name": "Tom"}]

reorderer_list = [{"order": 7, "name": "Tom"}, {"order": 5, "name": "Sara"}, {"order": 6, "name": "John"}]

def answer(initial_list, reorderer_list):
     sorted_order = sorted([e["order"] for e in reorderer_list])
     d = { e["name"]: order
           for e, order in zip(reorderer_list, sorted_order) }
     for e in initial_list: 
         e["order"] = d[e["name"]] 
0 голосов
/ 03 июля 2019

Как насчет этого?

def change_order_value(items):
    new_orders = [item['order'] for item in sorted(items, key=lambda x: x['order'])]
    for new_order, item in zip(new_orders, items):
        item['order'] = new_order
    return items


reorderer_list = [{"order": 7, "name": "Tom"}, {"order": 5, "name": "Sara"}, {"order": 6, "name": "John"}]
print(change_order_value(reorderer_list))
# [{'order': 5, 'name': 'Tom'}, {'order': 6, 'name': 'Sara'}, {'order': 7, 'name': 'John'}]

...