0

so i am trying to sort a list of members by their 'id' in a new list. the problem is that python tells me that the index is out of range which i don't understand since i do have a value at that index spot in the list.

here my code

members = [
  {'id': 1, 'firstname': 'johnny', 'lastname': 'doe'    },
  {'id': 3, 'firstname': 'sky',    'lastname': 'smith'  },
  {'id': 4, 'firstname': 'mary',   'lastname': 'johnes' },
  {'id': 2, 'firstname': 'frank',  'lastname': 'sanchez'}
]

NewMembers = []
i = 0
ids = 1

while len(NewMembers) != len(members):
    if ids == members[i]['id']:
        NewMembers.append(members[i])
        ids += 1
    else:
        i += 1

print(NewMembers)

output

line 8, in <module>
if ids == mymembers[i]['id']:
          ~~~~~~~~~^^^
IndexError: list index out of range
  • 1
    You're looking for 1. You find it an entry #0. Now `ids` is 2 and `i` is 0. You go looking for 2, but there is no entry with an id of 2. so you keep bumping `i` until it runs off the end of the list. – Tim Roberts Jan 09 '23 at 22:02
  • 3
    Is there a reason you're not using the built-in `sorted()` function? – Barmar Jan 09 '23 at 22:02
  • Do you just want `members.sort( key=lambda i: i['id'] )`? – Tim Roberts Jan 09 '23 at 22:02
  • This algorithm only works if all the IDs are sequential. But you're missing ID 2, so it runs off the end of the list looking for it. – Barmar Jan 09 '23 at 22:04

4 Answers4

1

If you want to use a lambda expression:

NewMembers = members.copy()
NewMembers.sort(key=lambda member : member['id'])

If you don't want to use lambdas:

def getID(member):
    return member['id']

NewMembers = members.copy()
NewMembers.sort(key=getID)
buffman23
  • 36
  • 3
0

Consider your logic with your sample. It will only work if the IDs are already sorted. Otherwise i will continue to be incremented until an out of bounds access occurs.

You should be using sorted which allows you to specify a key to sort on. In this case a lambda that returns the id of each element.

print(sorted(members, key=lambda x: x['id']))
Chris
  • 26,361
  • 5
  • 21
  • 42
0

If You wanna select people with specific id You can use the code below:

members = [{'id': 1, 'firstname': 'johnny', 'lastname': 'doe'},{'id': 3, 'firstname': 'sky', 'lastname': 'smith'},{'id': 4, 'firstname': 'mary', 'lastname': 'johnes'},{'id': 3, 'firstname': 'frank', 'lastname': 'sanchez'}]

NewMembers = []
i = 0
ids = 1
while i != len(members):
    if ids == members[i]["id"]:
        NewMembers.append(members[i])
    i += 1

print(NewMembers)
aljustiet
  • 11
  • 4
0

Yes you have a value, but it became too big At one moment your cycle is reaching i>3, that means it is trying to get

if ids == members[4]['id']

So this is out of range of your values

If you want to use cycle, much better to use "for". Here's how:

members = [{'id': 1, 'firstname': 'johnny', 'lastname': 'doe'},{'id': 3, 'firstname': 'sky', 'lastname': 'smith'},{'id': 4, 'firstname': 'mary', 'lastname': 'johnes'},{'id': 3, 'firstname': 'frank', 'lastname': 'sanchez'}]

new_members = []
max_difference = 0

for m in members:
    if m['id'] > max_difference: max_difference = m['id']

for n, member in enumerate(members):
    if n == 0:
        new_members.append(members[n])
        continue

    right_i = -1
    left_i = -1
    duplicate = -1
    right_difference = -max_difference
    left_difference = max_difference
    for i, new_member in enumerate(new_members):

        if (
            abs(new_member['id'] - member['id']) == new_member['id'] - member['id']
            and
            right_difference < new_member['id'] - member['id']
            ):
            right_difference = new_member['id'] - member['id']
            right_i = i
        elif (
            abs(new_member['id'] - member['id']) != new_member['id'] - member['id']
            and
            left_difference > new_member['id'] - member['id']
            ):
            left_i = i
        elif new_member['id'] - member['id'] == 0:
            new_members.append(members[n])
            duplicate = i
            break

    if duplicate != -1: new_members.insert(duplicate, members[n])
    elif left_i != -1: new_members.insert(left_i+1, members[n])
    else: new_members.insert(right_i, members[n])
            

print(new_members)

Not the most beautiful sorting algo, but uses only cycles and works 100% with any amount of input (if id is integer)