1

I have a list of object, each object contains a unique ID. The current list is like so:

[{"id": 3}, {"id": 5}, {"id": 8}]

I want to change the indexes a bit - instead of the dictionary with id = 3 to be on index 0, I want the dictionary with id = 3 to be on index 3.

I have tried:

list = []
for item in items:
    list[item["id"]] = item

but that gives me indexing error. Then I tried to do the following:

list = []
for item in items:
    list.insert(item["id"], item)

which just acts like a regular append (does not insert at specified index).

I have a last ditch attempt to do this on the front end when I am getting the response from the API but that defeats the whole purpose of reducing the amount of looping I do on the client side. The reason being is that the server can knock out these loops in like 50 milliseconds and on the client side it takes up to 300 milliseconds since it runs in the browser.

5
  • 1
    You can't insert into an empty list at index 3. The first element you add to a list will always be at index 0. You can either (a) use a dictionary instead of a list, or (b) pre-fill the list will a specific number of None values. Commented May 4, 2022 at 13:30
  • ^^^ this, and also, do yourself a favour and don't override the list keyword Commented May 4, 2022 at 13:31
  • And what in case if id not match with index do you want to store None there ? Commented May 4, 2022 at 13:31
  • 1
    what would be the expected output here? Commented May 4, 2022 at 13:34
  • @jkoestinger this isn't my actual code, I just posted this for stack overflow. The list keyword is fine :) Commented May 4, 2022 at 13:39

5 Answers 5

1

There is no problem in your code it all happens because your list has zero element

items = [{"id": 3}, {"id": 5}, {"id": 8}]
list_ = []
for item in items:
    while item['id'] > len(list_):
        list.append(None)
    list_.insert(item["id"], item)
print(list_)

OUTPUT:

You can see here your elements are inserted inside the list.

[None, None, None, {'id': 3}, None, {'id': 5}, None, None, {'id': 8}, None]

The above code works perfectly if the dictionary inside the list is in increasing order, But if the dictionary is in random order then first you need to first change the list to increasing order.


items = [{"id": 3}, {"id": 5}, {"id": 8},{'id':2}]
items = (sorted(items,key=lambda e:e['id'])) # sort the list
list_ = [] 
for item in items:
    while item['id'] > len(list_):
        list.append(None)
    list_.append(item)
print(list)

INPUT/OUTPUT

IN:items = [{"id": 3}, {"id": 5}, {"id": 8},{'id':2}]

OUTPUT FROM FIRST ANSWER:[None, None, {'id': 2}, None, {'id': 3}, None, {'id': 5}, None, None, {'id': 8}]

OUTPUT FROM SECOND ANSWER:[None, None, {'id': 2}, {'id': 3}, None, {'id': 5}, None, None, {'id': 8}]

Sign up to request clarification or add additional context in comments.

9 Comments

Yes, but the issue is that I do not know what is going to be the maximum index of the array. For all I know the ID could be 105126 or some absurd number like that. And allocating an array with a million elements each time I need to do this even when I have only a few elements seems like a waste of memory.
@DimitarVeljanovski Check now.
Thanks, I guess I have to do an extra loop to find the largest key to pre-fill to. I was hoping there is a more elegant solution but that are the tools which have been given to us by the python gods 😅😅.
This (and all the similar approaches) works for small IDs, but what if the IDs are in the millions or billions, or just a random int, or non-numeric?
@SharimIqbal there is some sort of rule now - a bit of time needs to pass for me to accept your answer.
|
1

I think the general solution for this will be

a= [{"id": 3}, {"id": 5}, {"id": 8}]
l = [None for _ in range(max(a,key=lambda x: x["id"])["id"]+1)]
for item in a:
    l[item["id"]]= item
print(l)

Also insert and item assignment is creating error because it expects that index to be exist beforehand so in that case you need to initialize your list with empty labels

Comments

0

Create an empty list with needed indexes first like

data = [{"id": 3}, {"id": 5}, {"id": 8}]
mod_list = [None]*max(x.get("id") for x in data)

Now fill the indexes with needed data

[mod_list.insert(x.get("id"),x) for x in data]

You get a list like this

[None, None, None, {'id': 3}, None, {'id': 5}, None, None, {'id': 8}, None, None]

The None indexes can be ignored in processing.

Comments

0

You can't insert into an empty list at index 3. The first element you add to a list will always be at index 0. More general, you can't insert at an index that's higher than the list is long. If you want a quick way to look up items with a specific index, use another dict instead of a list as the container:

>>> lst = [{"id": 3}, {"id": 5}, {"id": 8}]
>>> d = {x["id"]: x for x in lst}
>>> d
{3: {'id': 3}, 5: {'id': 5}, 8: {'id': 8}}
>>> d[3]
{'id': 3}

This way, each element can be looked up in O(1) using its ID as the index. And this will also work if the IDs are very large numbers (when its impractical to create a mostly empty list with that many indices) or even non-numeric, e.g. strings.

Comments

0

You can do below steps;

x = [{"id": 3}, {"id": 5}, {"id": 8}]
    
x.insert(3, x[0])
del x[0]

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.