I want to check if the current id
equals last id
1, (this should work for any number of similar dicts added in the list)
Code
listing = [
{
'id': 1,
'stuff': "othervalues"
},
{
'id': 2,
'stuff': "othervalues"
},
{
'id': 3,
'stuff': "othervalues"
}
]
for item in listing :
if item[-1]['id'] == item['id'] 1:
print(True)
Output
Traceback (most recent call last):
File "C:\Users\samuk\Desktop\Master\DV\t2\tester.py", line 10, in <module>
if item[-1]['id'] == item['id'] 1:
KeyError: -1
Desired result
True
or, in case of fail,
False
CodePudding user response:
To check if all the id
s are in a sequence we can use enumerate
here.
def is_sequential(listing):
start = listing[0]['id']
for idx, item in enumerate(listing, start):
if item['id'] != idx:
return False
return True
CodePudding user response:
You can save the last id in a variable.
id = listing[0]['id']
for item in listing[1:]:
if id == item['id']:
print(True)
else:
print(False)
id = item['id']
CodePudding user response:
As the saying goes... "There are many ways to skin a cat". So here's another way:
listing = [
{
'id': 1,
'stuff': "othervalues"
},
{
'id': 2,
'stuff': "othervalues"
},
{
'id': 3,
'stuff': "othervalues"
}
]
for i, v in enumerate(listing[1:], 1):
print(v['id'] - 1 == listing[i-1]['id'])
Of course, rather than just checking like this you could always sort the list!
CodePudding user response:
When you do for item in some_list
, item
is the actual item in that list. You can't get the previous item by item[-1]
.
So in your case, item
is a dictionary that has the keys 'id'
and 'stuff'
. Obviously, no key called -1
, so you get a KeyError
.
You can iterate over two slices of the list after using zip()
-- one that starts at the zeroth element, and one that starts on the first element. Using zip()
, you can get corresponding items of these slices simultaneously. You'll have every item and its subsequent item coming out of zip()
.
Also, you want a result after you've checked all pairs of items, not while you're checking each pair. To do this, create a variable is_sequential
with an initial value of True
. If you find a single pair that doesn't work, change this to False
, and break out of the loop because one pair being non-sequential makes the entire list so.
is_sequential = True
for item1, item2 in zip(listing, listing[1:]):
if item1['id'] 1 != item2['id']:
is_sequential = False
break
print(is_sequential)
Alternatively, you could use the any()
function with the same loop and condition, and then invert the result, or use all()
with the opposite condition:
# use any()
is_sequential = not any( item1['id'] 1 != item2['id']
for item1, item2 in zip(listing, listing[1:])
)
# or, use all()
is_sequential = all( item1['id'] 1 == item2['id']
for item1, item2 in zip(listing, listing[1:])
)
CodePudding user response:
You could also use sorted
and range
to evaluate if the identifiers are sequential:
def is_sequential(records: dict, key: str) -> bool:
values = [value[key] for value in records]
return sorted(values) == list(range(min(values), max(values) 1))
print(is_sequential(listing, "id"))
Note: Solution is based on approach #1 in this example and only works with integers.
However, I like Pranav Hosangadi's approach with a list comprehension better. But I would replace not any()
with all()
as suggested by Ch3steR in the comments:
def is_sequential(records: dict, key: str) -> bool:
return all(l[key] 1 == r[key] for l, r in zip(records, records[1:]))
print(is_sequential(records, "id"))
Ch3steR's solution is probably the most readable code.