Reputation: 440
I am newbie to python, trying to understand the concepts. I am trying to traverse a list, where inside list, I have kept dictionary data set which are initialized. I have defined function to traverse and the retrieve data.
Initially first key and value will be assigned to activeConfiguration list i,e activeConfiguration = ['Mammals','dogs']
and this activeConfiguration is passed as an param for getNextConfig(data, activeConfiguration)
function along with entity data.
My goal is that after some certain steps when I make function call getNextConfig(data, activeConfiguration)
it should retrieve next value for from the list for the particular key. the expected out I have specified below.
My code has bug, please help me to fix and to get desired result. Thanks for the help in advance.
#Entity data initialization
vertebrateAnimalsDict = [
{
"Reptiles": "Snakes, lizards, crocodiles, alligators, turtles"
},
{
"Mammals": "dogs, cats, horses, duckbill platypuses, kangaroos, dolphins, whales"
},
{
"Minibeasts": "Insects, spiders, crustaceans"
}
]
My function calls :
activeConfiguration = ['Mammals','dogs']
activeConfiguration = getNextConfig(vertebrateAnimalsDict, activeConfiguration)
print(activeConfiguration)
#some tasks in between
...
activeConfiguration = getNextConfig(vertebrateAnimalsDict, activeConfiguration)
print(activeConfiguration)
#some other tasks inbetween
...
activeConfiguration = getNextConfig(vertebrateAnimalsDict, activeConfiguration)
print(activeConfiguration)
My CODE :
#!/usr/bin/env python
def getNextConfig(data, activeConfiguration):
key_count=len([ele for ele in data if isinstance(ele,dict)])
val_index=-1
for dic in data:
for k,v in dic.items():
if k==activeConfiguration[0]:
key_index=next((i for i,d in enumerate(data) if k in d), None)
v=data[key_index][k]
v = v.split(',')
val_index=v.index(activeConfiguration[1])
if val_index != (len(v)-1):
return [k,v[val_index+1]]
elif key_index==(key_count-1) and val_index == (len(v)-1):
return []
else:
val_index=0
key_index=key_index+1
break
if val_index==0:
v=data[key_index][k]
v = v.split(',')
return [k,v[val_index]]
else:
continue
My Expected Output result :-
Reptiles : Snakes
Reptiles : lizards
Reptiles : crocodiles
Reptiles : alligators
Reptiles : turtles
Mammals : dogs
Mammals : cats
and so on ...
Upvotes: 0
Views: 165
Reputation: 2787
It would be simple to do the following:
Create one dictionary from the list of dictionaries:
dict1 = {k: v.split(", ") for x in vertebrateAnimalsDict for k, v in x.items()}
Convert this to a series and explode (so each item in the list of values is on a different row):
pairs = pd.Series(dict1).explode()
This small function:
def getNextConfig(pair):
# get list of bools for whether item matches, and "shift"
x = pairs[[False] + list(pairs == pair[1])[:-1]]
# print the pair, for example
print([x.index.item(), x.item()])
# return the pair
return [x.index.item(), x.item()]
Then running the code from the start:
pair = ["Reptiles", "Snakes"]
pair = getNextConfig(pair) # repeat this line to the end (and error on the very last, where it cannot continue)
And the old answer's loop, just in case you decide that you will loop through every combination or want to do this in the future:
for k, v in dict1.items():
for idx in range(len(v)):
print([k, v[idx]])
# the other code here...
Without the use of Pandas, you can instead "flip" the dictionary:
pairs = {}
for k, v in dict1.items():
for idx in range(len(v)):
pairs.update({v[idx]: k})
As all the items in the lists for reptiles, mammals, and minibeasts will be unique, you can change the values to keys and these three categories to values.
Then when calling the function you can reverse these when returning the pair (I have written a list comprehension to search the list of keys, "animals", instead of searching for values in a Pandas Series):
def getNextConfig(pair):
# get list of bools for whether item matches, and "shift"
p = [i+1 for i, y in enumerate(pairs.keys()) if y==pair[1]][0]
if len(pairs.keys()) <= p:
# print statement if out of items
print("Previous pair was last pair")
# return same pair (i.e. the last pair)
return pair
# animal
x = list(pairs.keys())[p]
# print the pair
print([pairs[x], x])
# return the pair
return [pairs[x], x]
Note that I have included an if statement for the last pair so that you a specific message can be written.
Upvotes: 1
Reputation: 147196
If I understand your question correctly, you could just use a generator to iterate the values:
def getNextConfig(data):
for dic in data:
for key, value in dic.items():
values = value.split(', ')
for v in values:
yield key, v
You might then loop over it like this:
configs = getNextConfig(vertebrateAnimalsDict)
for k, v in configs:
print(f'{k} : {v}')
Output (for your sample data):
Reptiles : Snakes
Reptiles : lizards
Reptiles : crocodiles
Reptiles : alligators
Reptiles : turtles
Mammals : dogs
Mammals : cats
Mammals : horses
Mammals : duckbill platypuses
Mammals : kangaroos
Mammals : dolphins
Mammals : whales
Minibeasts : Insects
Minibeasts : spiders
Minibeasts : crustaceans
Or to match your code style in the question, we use next
to fetch the next value from the generator:
configs = getNextConfig(vertebrateAnimalsDict)
activeConfiguration = next(configs, None)
if activeConfiguration is not None:
# do something with it
Note we supply a default value to next
to avoid a StopIteration
error.
Upvotes: 1