(I am using Python 3.8) The problem is as follows: I have the following data
items = [{season: 3, id: 1}, {season: 5, id: 2}, {season: 10, id: 3}, {season: 8, id:4}]
And I would like to rearrange this list moving to the head the elements from seasons, e.g., 8 and 10. For that, I have another list with the elements from that subset:
items_to_top = [{season: 10, id: 3}, {season: 8, id:4}]
I know this is not the most efficient way to do this, but it has to be like this since I have to respect some interfaces. In order to move them to the top of the former list I am doing
for item in items_to_top:
items.remove(item)
items.insert(0, item)
This operation is safe since items_to_top is extracted from items, therefore is a closed set.
I am looking for a more efficient/faster way to do this since when items grows (around 30k elements) and items_to_top grows as well (around 7k elements) the loop takes close to 1 minute to finish.
I have tried to transform everything to set but I can't since my data is unhashable (dicts) and inside the values of the dicts are also unhashable types (lists).
CodePudding user response:
You can create a set of tuples using the values of your dictionaries and create a new list like so:
top_set = {(d[season], d[id]) for d in items_to_top}
new_items = items_to_top [d for d in items if (d[season], d[id]) not in top_set]
The problem here is that everytime you use items.insert(0, item) you're creating a new list from scratch. Aditionally, the remove needs to search for the correct value from the beginning to the end of the list.
EDIT: Another approach, since you can't hash all the elements in the dictionaries.
for item in items_to_top[::-1]:
items.remove(item)
items.append(item)
items = items[::-1]
CodePudding user response:
Would it be possible for you to store the indexes of the top items instead (or in addition to) the items_to_top list ?
That would allow a more direct reorganization of the items list using indexing instead of searches.
For example:
items = [{'season': 3, 'id': 1}, {'season': 5, 'id': 2},
{'season': 10, 'id': 3}, {'season': 8, 'id':4}]
toTop = [2,3]
items = [items[i] for i in dict.fromkeys([*toTop,*range(len(items))])]
print(items)
[{'season': 10, 'id': 3}, {'season': 8, 'id': 4},
{'season': 3, 'id': 1}, {'season': 5, 'id': 2}]
