Turning @Tomerikoo's comment into an answer:
Use a list comprehension:
[o.name for o in l]
Note that this will not necessarily be more efficient than looping, but obviously more beautiful.
Answer from arne on Stack OverflowTurning @Tomerikoo's comment into an answer:
Use a list comprehension:
[o.name for o in l]
Note that this will not necessarily be more efficient than looping, but obviously more beautiful.
I think this will help you:
l = [<obj1>, <obj2>, <obj3>, <obj4>]
list(map(lambda x:x.name, l))
Python lists do have an index method. But it only finds values that are equal to the argument, not values that have an argument that matches your partial value.
There's really nothing in Python that finds partial-structure matches like this; you can search/filter/etc. on equality, or on a predicate function, but anything else you have to write yourself.
The easiest way to do this is with a loop. You can write it explicitly:
for index, element in enumerate(my_array):
if element["extension"] == ".py":
return index
… or in a comprehension:
return next(index for index, element in enumerate(array)
if element["extension"] == ".py")
Alternatively, you can turn the matching into a function, and pass it to filter, or use it as a key function in a more complex higher-order function, but there doesn't seem to be any real advantage to that here.
And of course you can write your own indexOf-like function that matches partial structures if you want.
You can write your own function to get the index:
>>> my_dict = {'files': [{'name': 'Markdown', 'extension': '.md'}, {'name': 'Python', 'extension': '.py'}, {'name': 'Sublime Text Setting', 'extension': '.sublime-settings'}]}
>>> def solve(key, val, lis):
return next((i for i, d in enumerate(lis) if d[key] == val), None)
...
>>> solve('extension', '.py', my_dict['files'])
1
How to get field value from array of objects in python? - Stack Overflow
python - Get array of a specific attribute of all objects from an array of objects - Stack Overflow
Searching Array of Data Objects
get array values in python - Stack Overflow
One strategy to identify bugs in this code is to remove all conditions in the if clause, then add them one by one and checking whether the result is as expected.
You use the function hasattr. This function checks whether an object has a specific attribute (member variable, e.g., data[0].segments). data[0], however, is a dict. Dicts don't have a member called segments. What you're looking for is whether the dict contains a key segments, which you can achieve with the in operator:
if "segments" in item:
...
Then, there's another issue in your code. item["segments"] is a list, so you must use integers to access its members. Therefore, you get the error
TypeError: list indices must be integers or slices, not str
This error points towards the statement seg_id in item["segments"]["id"]. You can solve this with a double for loop or set comprehension and set intersection:
set(filter_config["segment_ids"]) & {seg["id"] for seg in item["segments"]}
Sets are containers wherein each element is unique. The operator & computes the intersection of two sets, i.e., the set of elements that are in both sets. set(filter_config["segment_ids"]) converts your list of segment IDs (I assume, it's a list) into a set. The set comprehension {seg["id"] for seg in item["segments"]} creates a set containing each segment IDs from the segments in the current item. The set is evaluated as true in an if statement iff the set is not empty.
Then, you should get your desired result.
Again, when you have a complex expression that doesn't work as expected, try to break it down to simpler expressions and check whether they do what you expect. Especially when learning, you can use an interactive Python session to build complex commands step by step, e.g., adding more and more filters, until you get what you need.
If you write your code as a sequence of loops you'll find it easier to read and debug. Complex list comprehensions such as the one in your question serve no purpose other than to be unnecessarily esoteric and hard to debug and maintain.
You could consider using a generator to identify the dictionaries you're interested in.
Something like this:
import json
from collections.abc import Iterator
filter_config = {
"segment_ids": {"22222222", "1010101"},
"rubric_ids": {"345", "999", '123'}
}
# this will yield a dictionary if ANY of the "segments" "id" values are in the specified set
# and if the "rubric" "id" is in its set
def gen_valid_dictionaries(data: list[dict]) -> Iterator[dict]:
for d in data:
for s in d.get("segments", []):
if s.get("id") in filter_config["segment_ids"]:
id_ = d.get("rubric", {}).get("id")
if id_ in filter_config["rubric_ids"]:
yield d
break
with open("foo.json") as f:
data = json.load(f)
filtered_data = [d for d in gen_valid_dictionaries(data)]
I would probably use the getattr built-in function for this purpose.
>>> my_object.my_attribute = 5
>>> getattr(my_object, 'my_attribute')
5
To create the numpy array as you would want:
def get_attrs(obj, attributes):
"""Returns the requested attributes of an object as a separate list"""
return [getattr(obj, attr) for attr in attributes]
attributes = ['a', 'b', 'c']
attributes_per_object = np.array([get_attrs(obj, attributes) for obj in all_objects])
This answer is inspired from the answer of @energya using the getattr built-in function. As that answer makes a function to get a list of attributes of a specific object, while the question was for getting a list of one specific attribute for all the objects in the array of objects.
So using getattr function,
>>> my_object.my_attribute = 5
>>> getattr(my_object, 'my_attribute')
5
For getting a numpy array of a specific attribute of all objects:
def get_attrs(all_objects, attribute, args=None):
"""Returns the requested attribute of all the objects as a list"""
if(args==None):
# If the requested attribute is a variable
return np.array([getattr(obj, attribute) for obj in all_objects])
else:
# If the requested attribute is a method
return np.array([getattr(obj, attribute)(*args) for obj in all_objects])
# For getting a variable 'my_object.a' of all objects
attribute_list = get_attrs(all_objects, attribute)
# For getting a method 'my_object.func(*args)' of all objects
attribute_list = get_attrs(all_objects, attribute, args)
You can use zip() function:
for zipped in zip(arr1.split(",") , arr2.split(",")):
someDictionary[zipped[0]] = zipped[1]
zip() creates tuple for each pair of items in collections, then you map one to another. If your 'arrays' have diffrent length, you can use map():
a = [1,3,4]
b = [3,4]
print map(None, a, b)
[(1, 3), (3, 4), (4, None)]
You should be able to do this with python's enumerate function. This lets you loop through a list and get both its numerical index and its value:
array1 = arr1.split(',')
array2 = arr2.split(',')
for i,value in enumerate(array1):
print value, array2[i]
This produces:
25 A
26 B
In Python, you don't have to declare a variable before using it.
The line:
protocolsFound = [num]
Is probably intended to create a list of size num, but you can either just create it as an empty list protocolsFound = [] and start filling it with .append(), or if you need to be able to access specific positions in the list, you can create a list with num empty positions like protocolsFound = [None for _ in range(num)]. This is rarely needed in well-written Python code, though.
It errors because you set the first index of protocolsFound to an in num
Take a look at this line an fix it,
protocolsFound = [num]
why do you need the num in there?