I think you want a dictionary where each key is the id and the value is your object.
Try the following. data is your array of data.
new = {}
for item in data:
item_id = item['test']['id']
new[item_id] = item
You could also use a dictionary comprehension.
new = {item['test']['id']: item for item in data}
Answer from Ozzy Walsh on Stack OverflowI think you want a dictionary where each key is the id and the value is your object.
Try the following. data is your array of data.
new = {}
for item in data:
item_id = item['test']['id']
new[item_id] = item
You could also use a dictionary comprehension.
new = {item['test']['id']: item for item in data}
Use itertools.groupby
from itertools import groupby
f = lambda d: d['test']['id']
res = {k:list(v) for k,v in groupby(sorted(l, key=f), f)}
pprint(res)
Output
{'2008': [{'info': {'a': 65535, 'b': 50},
'test': {'id': '2008', 'm': '10300'}},
{'info': {'a': 65535, 'b': 50},
'test': {'id': '2008', 'm': '10300'}}],
'2009': [{'info': {'a': 65535, 'b': 50},
'test': {'id': '2009', 'm': '10300'}}]}
You may be looking for pandas, which provides handy datatypes that wrap numpy arrays, allowing you do access rows and columns by name instead of just by number.
I dislike giving ready made answers - but I think it would take much more time to explain it in English -
The basic idea to fetch objects the way numpy does is to customize the __getitem__ method - comma separated values are presented to the method as tuples - you them just use the values in the tuple as indexes to your nested dictionaries in sequence.
Beyond that, Python made easy to create fully functional dict equivalentes with the collections.abc classes: if you implement a minimal set of methods when inhetiring from collections[.abc].MutableMapping, all dictionary behavior is emulated - (__getitem__, __setitem__, __delitem__, __iter__, __len__) - Then, it is just a matter of proper iterating through the key components, and create new, empty, regular dictionaries to store the needed values.
try:
from collections import MutableMapping
except ImportError:
# Python3 compatible import
from collections.abc import MutableMapping
class NestedDict(MutableMapping):
def __init__(self, *args, **kw):
self.data = dict(*args, **kw)
def get_last_key_levels(self, key, create=False):
if not isinstance(key, tuple):
key = (key,)
current_data = self.data
for subkey in key:
previous = current_data
current_data = current_data[subkey] if not create else current_data.setdefault(subkey, {})
return previous, current_data, subkey
def __getitem__(self, key):
previous, current_data, lastkey = self.get_last_key_levels(key)
return current_data
def __setitem__(self, key, value):
previous, current_data, lastkey = self.get_last_key_levels(key, True)
previous[lastkey] = value
def __delitem__(self, key):
previous, current_data, lastkey = self.get_last_key_levels(key)
del previous[lastkey]
def __iter__(self):
return iter(self.data)
def __len__(self):
return len(self.data)
def __repr__(self):
return "NestedDict({})".format(repr(self.data))
And you are set to go:
>>> from nesteddict import NestedDict
>>> x = NestedDict(a={})
NestedDict({'a': {}})
>>> x["a", "b"] = 10
>>> x
NestedDict({'a': {'b': 10}})
>>> x["a", "c", "e"] = 25
>>> x
NestedDict({'a': {'c': {'e': 25}, 'b': 10}})
>>> x["a", "c", "e"]
25
>>>
Please note that this is a high-level implementation, which will just work, but you will have nowhere near the optimization level you get on NumPy with this - to the contrary. If you will need to perform fast data operations in these objects, you maybe could check "cython" - or resort to your idea of transposing the dict keys to nuemric keys and use NumPy (that idea could still pick some ideas from this answer)
arrays - store value with multidimensional key pair in python - Stack Overflow
Multidimensional arrays?
Multidimensional array in Python - Stack Overflow
How to get key filtered by its value in multidimensional array Python - Stack Overflow
Hello!
I have 5 sets, each set contains a number of elements of variable length (eg. set 1 has 100 elements, set 2 has 150 and so on)
Is it possible to store these sets in a single structure?
For example, if I want to print the 35th elements of the 3rd set, I could call it simply by saying something like MyContainer[setN][elementN]
I was trying to use a 2D array but I can't initialize its shape, since each set has a variable number of elements.
Can anybody point me to the right direction / best practice?
Thank you
If you restrict yourself to the Python standard library, then a list of lists is the closest construct:
arr = [[1,2],[3,4]]
gives a 2d-like array. The rows can be accessed as arr[i] for i in {0,..,len(arr}, but column access is difficult.
If you are willing to add a library dependency, the NumPy package is what you really want. You can create a fixed-length array from a list of lists using:
import numpy
arr = numpy.array([[1,2],[3,4]])
Column access is the same as for the list-of-lists, but column access is easy: arr[:,i] for i in {0,..,arr.shape[1]} (the number of columns).
In fact NumPy arrays can be n-dimensional.
Empty arrays can be created with
numpy.empty(shape)
where shape is a tuple of size in each dimension; shape=(1,3,2) gives a 3-d array with size 1 in the first dimension, size 3 in the second dimension and 2 in the 3rd dimension.
If you want to store objects in a NumPy array, you can do that as well:
arr = numpy.empty((1,), dtype=numpy.object)
arr[0] = 'abc'
For more info on the NumPy project, check out the NumPy homepage.
To create a standard python array of arrays of arbitrary size:
a = [[0]*cols for _ in [0]*rows]
It is accessed like this:
a[0][1] = 5 # set cell at row 0, col 1 to 5
A small python gotcha that's worth mentioning: It is tempting to just type
a = [[0]*cols]*rows
but that'll copy the same column array to each row, resulting in unwanted behaviour. Namely:
>>> a[0][0] = 5
>>> print a[1][0]
5
It does what you need. .items() returns data as iterable objects that can be traversed.
for key, value in employee_detail_list.items():
if value["company"] == "Company 2":
print(key)
# Output
Tom Smith
Andrew Sebastian
The problem with your solution is that val_list = list(employee_detail_list.values()) returns a list with objects and you are trying to find val_list.index("Company 2") by string which is not there
You can use filter()
employee_detail_list = {
'John Doe': {
'name': 'EMP-0001',
'first_name': 'John',
'last_name': 'Doe',
'full_name': 'John Doe',
'company': 'Company 1'
},
'Tom Smith': {
'name': 'EMP-0002',
'first_name': 'Tom',
'last_name': 'Smith',
'full_name': 'Tom Smith',
'company': 'Company 2'
},
'Andrew Sebastian': {
'name': 'EMP-0003',
'first_name': 'Andrew',
'last_name': 'Sebastian',
'full_name': 'Andrew Sebastian',
'company': 'Company 2'
}
}
def isFromCompany2(data):
return data["company"] == "Company 2"
result = filter(isFromCompany2, employee_detail_list.values())
print(list(result))
This is a nice article that explains it https://realpython.com/python-filter-function/
myhash['john'] is itself a dictionary. (You aren't creating a multi-dimensional dictionary, but rather a dictionary of dictionaries.)
Thus...
last_names = list(myhash['john'])
or if you want to do something in a loop...
for last_name in myhash['john']:
# do something with last_name
I already mentionned it when answering your previous question : it looks like you're trying to reinvent the square wheel. Given your stated need, chances are you'll want to do a lookup on the lastname part too, and then it's either back to step 1 (browsing the whole dataset sequentially testing the "2nd-level" key) or maintaining a "lastname" index storing lastname:[firstname1, firstname2, firstnameN] which reduces (but not supress) the sequential browsing and needs to be updated on any insert or delete.
IOW you're reimplementing most of what a relational database can do, and it's very unlikely your implementation will be faster or more robust than even the cheaper RDB. For the record, there are very lightweight, file based (no need for a server process etc) RDB engines like SQLite3 (Python bindings are in the stdlib so you don't even have to install anything special).