so I was writing a function consume a list to count how many different types of data in it and return a list of natural numbers by an order of integer, float, string, Boolean, other
[integer, float, string, Boolean, others]
for example let
L = [1, "123", !, #, 2.0, True, False, [1,2]]
then funcition(L) will return
[1, 1, 1, 2, 3]
I choose the built-in function type() to determine the data type for example
type(L[0]) == type(9)
then I know if first element of the list is an integer. but when the list contains some symbols like "!@#$%^", then the type() function doesn't work anymore, it will display
Syntax Error: invalid syntax: <string>
So I wonder if there is another way to classify symbols and put them into the "other" type.
It is not the type(..)
function that does not work: the error occurs when constructing the list .
When a compiler/interpreter reads code, it will aim to generate an abstract syntax tree according to the grammar of the language. !
and #
are simply invalid grammar . The #
is interpreted as the start of a comment, so the interpreter will read:
L = [1, "123", !,
But that does not make any sense either since !
is not valid, and even if you would remove the !
, then Python will still complain it cannot find a matching ]
(to close the list).
Now let's assume you sort that out, there is another problem: what with subclassing ? One can for instance subclass a str
ing. Do you count it as a str
or other? The problem is more troublesome because Python supports multiple inheritance: something can be a str
ing and a bool
at the same time . Let us assume we only count real str
ings and not subclasses, then we can write the following code:
def count_types(data):
the_types = [int,float,str,bool]
result = [0]*(len(the_types)+1)
for x in data:
tyx = type(x)
for idx,ty in enumerate(the_types):
if tyx is ty:
result[idx] += 1
break
else:
result[-1] += 1
return result
This would produce:
>>> count_types([1, "123", 2.0, True, False, [1,2]])
[1, 1, 1, 2, 1]
Nevertheless it is weird that you want to return a list without context , and furthermore that you only count specific types. I guess a more elegant and faster solution, is to generate a Counter
with types:
from collections import Counter
result = Counter(type(x) for x in data)
This generates:
>>> Counter(type(x) for x in data)
Counter({<class 'bool'>: 2, <class 'list'>: 1, <class 'str'>: 1, <class 'float'>: 1, <class 'int'>: 1})
If you want to compare types (even though it's not a Pythonic way) you need to use isinstance()
isinstance(L[0], type(9))
or
isinstance(L[0], str)
You can use a dictionary to count your types, then use operator.itemgetter()
in order to get the desire result based on your expected order:
In [32]: order = [int, float, str, bool, 'other']
In [33]: l = [1, 3, 5.6, 'st', True, 'gg', False, None, lambda x: 3, sum]
In [34]: from collections import defaultdict
In [35]: from operator import itemgetter
In [36]: d = defaultdict(int)
In [37]: for i in l:
t = type(i)
if t in order:
d[t] += 1
else:
d['other'] += 1
....:
In [38]: itemgetter(*order)(d)
Out[38]: (2, 1, 2, 2, 3)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.