Changing a nested list using a tuple as a path - python

I have some data from another program (Grasshopper) that is roughly equivalent to an ordered dict and can be converted into the form
[ (0,0,0):[info], (0,0,1):info, (0,1,0):info ]
I can convert this into a list of tuples and a list of info but my end goal is to recreate the structure as a nested list i.e.
[[[info, info], [info]]]
The info can be of any type so could be a list or a float etc.
The problem is that the tuples can be of arbitrary length so I do not know in advance how many dimensions I will have in the nested list. This means I cannot use the list[x][y] method and I haven't managed to get a recursive function to assign an immutable type (the info).
Does anyone have any ideas? Thanks!

why not just do something with a defaultdict and list?
from collections import defaultdict
d = defaultdict(list)
for gds in grasshopper_data_structs:
for k, v in gds.items():
d[k].append(v)

Related

How to iterate over dictionaries in a list and extract key values to a separate list

I'm trying to match key value from different dictionaries in a list and make them as individual list.Below is the example format
originallist=[
{"A":"Autonomous","C":"Combined","D":"Done"},
{"B":"Bars","A":"Aircraft"},
{"C":"Calculative"}
]
#Note: The dictionaries present in the original list may vary in number
#I was trying to acheive the below format
A=["Autonomous","Aircraft"]
B=["Bars"]
C=["Calculative","Combined"]
D=["Done"]
Thanks in advance for your help
The best option would be to use a defaultdict.
from collections import defaultdict
out = defaultdict(list)
#data is the list in question
for rec in data:
for key,value in rec.items():
out[key].append(value)
A defaultdict returns a default value in case the key does not exist. dict.items is a method that returns and iterator of the key value pairs.
You can do it faster using pandas, but it would be overkill unless you have a huge dataset.

Idiomatic way to get key from a one-item Python dict not knowing this key (but knowing the dict has only one item)?

I have a list of one-item dicts (parsed from JSON) that looks like this:
lst = [
{"key_0": "value_0"},
{"key_1": "value_1"},
{"key_2": "value_2"},
...
{"key_n": "value_n"}
]
what would be the most elegant way to retrieve a key from the list's n-element not knowing this key?
I came up with:
[*lst[n].keys()][0]
but it looks somewhat ugly to me.
You can create an iterator from the dict and use the next function to obtain the first item:
next(iter(lst[n]))
You can convert direct keys to list and then get first item
>>> n = 0
>>> list(lst[n])[0]
'key_0'

summing dict value of list to single integer

I am trying to do something pretty simple but cant seem to get it. I have a dictionary where the value is a list. I am trying to just sum the list and assign the value back to the same key as an int. Using the code below the first line doesn't do anything, the second as it says puts the value back but in a list. All other things ive tried has given me an error can only assign iterable. As far as i know iterables are anything that can be iterated on such as list and not int. Why can I only use iterable and how can i fix this issue ? The dict im using is here (https://gist.github.com/ishikawa-rei/53c100449605e370ef66f1c06f15b62e)
for i in dict.values():
i = sum(i)
#i[:] = [sum(i) / 3600] # puts answer into dict but as a list
You can use simple dictionary comprehension if your dict values are all lists
{k:sum(v) for k, v in dict.items()}
for i in dikt.keys():
dickt[i] = sum(dict[i]))
btw, dict is a type. best not to use it as a variable name

python dictionary float search within range

Suppose I have some kind of dictionary structure like this (or another data structure representing the same thing.
d = {
42.123231:'X',
42.1432423:'Y',
45.3213213:'Z',
..etc
}
I want to create a function like this:
f(n,d,e):
'''Return a list with the values in dictionary d corresponding to the float n
within (+/-) the float error term e'''
So if I called the function like this with the above dictionary:
f(42,d,2)
It would return
['X','Y']
However, while it is straightforward to write this function with a loop, I don't want to do something that goes through every value in the dictionary and checks it exhaustively, but I want it to take advantage of the indexed structure somehow (or a even a sorted list could be used) to make the search much faster.
Dictionary is a wrong data structure for this. Write a search tree.
Python dictionary is a hashmap implementation. Its keys can't be compared and traversed as in search tree. So you simply can't do it using python dictionary without actually checking all keys.
Dictionaries with numeric keys are usually sorted - by key values. But you may - to be on the safe side - rearrange it as OrderedDictionary - you do it once
from collections import OrderedDict
d_ordered = OrderedDict(sorted(d.items(), key =lambda i:i[0]))
Then filtering values is rather simple - and it will stop at the upper border
import itertools
values = [val for k, val in
itertools.takewhile(lambda (k,v): k<upper, d_ordered.iteritems())
if k > lower]
As I've already stated, ordering dictionary is not really necessary - but some will say that this assumption is based on the current implementation and may change in the future.

How to get value on a certain index, in a python list?

I have a list which looks something like this
List = [q1,a1,q2,a2,q3,a3]
I need the final code to be something like this
dictionary = {q1:a1,q2:a2,q3:a3}
if only I can get values at a certain index e.g List[0] I can accomplish this, is there any way I can get it?
Python dictionaries can be constructed using the dict class, given an iterable containing tuples. We can use this in conjunction with the range builtin to produce a collection of tuples as in (every-odd-item, every-even-item), and pass it to dict, such that the values organize themselves into key/value pairs in the final result:
dictionary = dict([(List[i], List[i+1]) for i in range(0, len(List), 2)])
Using extended slice notation:
dictionary = dict(zip(List[0::2], List[1::2]))
The range-based answer is simpler, but there's another approach possible using the itertools package:
from itertools import izip
dictionary = dict(izip(*[iter(List)] * 2))
Breaking this down (edit: tested this time):
# Create instance of iterator wrapped around List
# which will consume items one at a time when called.
iter(List)
# Put reference to iterator into list and duplicate it so
# there are two references to the *same* iterator.
[iter(List)] * 2
# Pass each item in the list as a separate argument to the
# izip() function. This uses the special * syntax that takes
# a sequence and spreads it across a number of positional arguments.
izip(* [iter(List)] * 2)
# Use regular dict() constructor, same as in the answer by zzzeeek
dict(izip(* [iter(List)] * 2))
Edit: much thanks to Chris Lutz' sharp eyes for the double correction.
d = {}
for i in range(0, len(List), 2):
d[List[i]] = List[i+1]
You've mentioned in the comments that you have duplicate entries. We can work with this. Take your favorite method of generating the list of tuples, and expand it into a for loop:
from itertools import izip
dictionary = {}
for k, v in izip(List[::2], List[1::2]):
if k not in dictionary:
dictionary[k] = set()
dictionary[k].add(v)
Or we could use collections.defaultdict so we don't have to check if a key is already initialized:
from itertools import izip
from collections import defaultdict
dictionary = defaultdict(set)
for k, v in izip(List[::2], List[1::2]):
dictionary[k].add(v)
We'll end with a dictionary where all the keys are sets, and the sets contain the values. This still may not be appropriate, because sets, like dictionaries, cannot hold duplicates, so if you need a single key to hold two of the same value, you'll need to change it to a tuple or a list. But this should get you started.

Categories

Resources