Spyros
Spyros

Reputation: 37

How I can count the objects from a key of dictionary?

I have this dictionary (ignore the "Rank" key):

dict={
    "asset": [("S3","A1"),"S2",("E4","E5"),("E1","S1"),"A6","A8"], 
    "Rank": lirank,
    "number_of_attributes":
}

Ι want to count the objects of the "asset" key and add it to "number_of_attributes" as a list.

Τhe output that I want is :

"number_of_attributes":[2,1,2,2,1,1]

the values come from the first object of asset ("S3","A1") having 2 items, the second ("S2") having 1 item, etc.

I would ideally like to write it with a for loop but I am open to other ideas.

Upvotes: 3

Views: 89

Answers (3)

MSurrow
MSurrow

Reputation: 1225

There are answers above that provides you with a fix for your problem. However, the reason that you are in trouble with this is that you are mixing datatypes in the asset list. This is not typically a good idea, and your problem here is a good example of why.

Normally, if you had a list of items and you wanted the "length" or "number_of_attributes", as you need in this case, you would just want to be able to do something like:

number_of_attribues = [len(x) for x in dict['asset']]

But len(..) behaves differently for tuple and string, and for string it doesn't give you the value you want (1) but the count of letters in the string (2).

This happens because the asset list you have has items of different data types. This list:

asset = [("S3","A1"),"S2",("E4","E5"),("E1","S1"),"A6","A8"]

is a list of tuples and strings mixed. You can see this by looping through the list and printing the data type:

>>> for a in asset:
...     print(type(a))
... 
<class 'tuple'>
<class 'str'>
<class 'tuple'>
<class 'tuple'>
<class 'str'>
<class 'str'>

If you can change your asset list to use lists instead of tuples, then you'd have a much simpler solution. Like so:

If you can change your input list to contain items of the same type:

asset_as_list = [["S3","A1"],["S2"],["E4","E5"],["E1","S1"],["A6"],["A8"]]

You now have a list of lists. The tuples are now a list of two items (you call them attributes here) and the strings are now a list of one item.

This will give you two good things:

1) It will allow you to get your number_of_attributes in a much simpler way:

>>> number_of_attribues = [len(x) for x in asset_as_list]
>>> number_of_attribues
[2, 1, 2, 2, 1, 1]

2) You don't mix datatypes in your list, and it will be much easier to work with in other situations as well as making your code easier to understand and debug. Which will become more important as your codebase grows larger and larger.

Upvotes: 1

tafaust
tafaust

Reputation: 1518

First, consider naming your variables different than dict, list or tuple.

Second, a solution to this issue is already provided here: https://codereview.stackexchange.com/questions/97217/deep-length-of-a-list

For your specific case:

myDict={"asset":[("S3","A1"),"S2",("E4","E5"),("E1","S1"),"A6","A8"], "Rank": lirank }

myDict["number_of_attributes"] = [len(itm) if isinstance(itm, tuple) else 1 for itm in myDict["asset"]]

print(myDict["number_of_attributes"])

Here is a link to an online python repl for your problem: https://repl.it/repls/SuperiorDisastrousMuse

Upvotes: 1

kederrac
kederrac

Reputation: 17322

you can use a list comprehension:

my_dict["number_of_attributes"] = [1 if isinstance(x, str) else len(x) for x in my_dict["asset"]]
print(my_dict["number_of_attributes"])

output:

[2, 1, 2, 2, 1, 1]

Upvotes: 6

Related Questions