Наиболее эффективный способ переупорядочения списка объектов с использованием свойства order, которое есть у каждого объекта
Я пытаюсь создать алгоритм, который будет проходить через список объектов и сортировать их, но не точно сортировать, как перемещение элементов списка на основе свойства, порядок исходного списка не меняется, что определяет порядок не то, как объекты сортируются внутри списка, а свойство, которое вызывал каждый объект 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"}]
не имеет значения, оба являются правильными (они оба являются правильными, потому что сортировка элементов внутри окончательного списка не имеет значения, значение имеет только 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 ответа
Как насчет этого?
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'}]
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"]]