There is an array consisting of nested arrays:
a = [ 'id': 20, 'child': ['id':21,'id':22], "child": [ ["id":23,"id:34]]
How can I get a list of all id's in one variable?
There is an array consisting of nested arrays:
a = [ 'id': 20, 'child': ['id':21,'id':22], "child": [ ["id":23,"id:34]]
How can I get a list of all id's in one variable?
Try to write more detailed questions. To get an answer, explain what exactly you see the problem, how to reproduce it, what you want to get as a result, etc. Give an example that clearly demonstrates the problem. If the question can be reformulated according to the rules set out in the certificate , edit it .
If the “array” in the question implies an associative array ( Mapping , dictionary in Python), which may contain nested index arrays ( Sequence , list in Python), which in turn may contain associative arrays, etc., then it is easy enough to write a recursive function, which returns all values that match the specified key:
#!/usr/bin/env python3 from collections import Sequence, Mapping def get_all_values(seq_or_mapping, key): """Get all values from *seq_or_mapping* with the *key* recursively.""" items = getattr(seq_or_mapping, 'items', lambda: enumerate(seq_or_mapping)) for k, value in items(): if k == key: yield value if isinstance(value, (Sequence, Mapping)): yield from get_all_values(value, key) # yield nested values
Example:
nested = {'id': 20, 'child': [{'id': 21}, {'id': 22, 'child': [{'id': 23}, {'id': 34}]}]} print(*get_all_values(nested, 'id')) # -> 20 21 22 23 34
The example presents only one of several possible interpretations of the structure shown in the question (it is ambiguous), but this does not affect the final set of id
.
If the key is integer, the function also returns values with the corresponding index from each list (or dictionary with key 0
), for example:
print(*get_all_values(nested, 0)) # -> {'id': 21} {'id': 23}
The string ( str
) is also the Sequence
(sequence) in Python, so if you want to treat the string as a scalar value, you should explicitly exclude this type (add to the loop body in the example code above before the recursive call):
if isinstance(value, str): continue # переходим к следующей паре ключ, значение
Instead of getattr()
, you could use a generic function to distinguish between a list and a dictionary, such as get_items()
.
If the structure can be very deeply nested, then instead of recursion, you can use an explicit stack with a loop :
def get_all_values(seq_or_mapping, key): stack = [seq_or_mapping] while stack: seq_or_mapping = stack.pop() for k, v in get_items(seq_or_mapping): if k == key: yield v if isinstance(v, (Sequence, Mapping)): stack.append(v)
In the commentary on the question I already wrote, why the structure described by you cannot be pushed neither into the list, nor into the dictionary.
You need to look for an alternative data structure. Alternatively, you can use a list of tuples: the list will contain 2-element tuples, in which the zero element is what you had the key (id or child), and the first element is what you had the value (the number for the key id or list for the key child).
Thus, your structure will look like this:
a = [('id', 20), ('child', [('id', 21), ('id', 22)]), ("child", [("id", 23), ("id", 34)])]
And the code for getting the list of all id will be like this:
ids = [] def proceed(lst): for tpl in lst: key, value = tpl if key == 'id': ids.append(value) if key == 'child': proceed(value) proceed(a) print(ids) # Код выведет: [20, 21, 22, 23, 34]
This is the easiest / most primitive option. I would on such a task, perhaps, introduce separate two classes for id and child and encapsulate all the logic in them. Well, or even get rid of the keys and kept this information like this:
[20, [21, 22], [23, 34]]
But it strongly depends on the final task.
import collections def getAllKey(obj: iter, key='id'): if isinstance(obj, dict): for k, v in obj.items(): if k == key: yield v elif isinstance(v, collections.Iterable): yield from getAllKey(v) elif isinstance(obj, collections.Iterable): for ob in obj: yield from getAllKey(ob) a = ({'id':20,"child":[{"id":23},{"id":34},{'child':[{'id':21},{'id': 22}]}]},{'id': 11}) r = list(getAllKey(a)) print(r)
out:
[23, 34, 21, 22, 20, 11]
getAllKey()
not a very good name (the function returns all values, not keys. You could call: get_all_values()
2- If there are no special reasons for the opposite, try to adhere to the pep-8 naming convention, namely instead of camelCase
, use: lower_case_with_underscores
for function names 3- the default value for key
probably not worth using here — the function doesn’t specifically tailor the 'id'
anything. If you use collections.Iterable
, you can use collections.Mapping
instead of dict then.Source: https://ru.stackoverflow.com/questions/566649/
All Articles
array()
. This is probably the source of the terminology in question - jfs