The code here works for me. But I am new to Python and want to know and learn if there is a more elegant or pythonic way to do that job.
There is a list of two-element-tuples. I want to join equal list elements and store the count of equal elements as a third tuple-element (the first in front of the other two-tuple elements).
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
org = [ ( 12, 4 ),
( 8, 4 ),
( 12, 8 ),
( 12, 8 ) ]
# should result in
# [ ( 1, 12, 4 ),
# ( 1, 8, 4 ),
# ( 2, 12, 8 ) ]
def count_element(count_in, e):
"""
How often does 'e' appear in 'count_in'.
"""
count = 0
for x in count_in:
if x == e:
count += 1
return count
def has_element(look_in, e):
"""
'look_in' is a three-element tuple
'e' is a two-element tuple
"""
for x, y, z in look_in:
if y == e[0] and z == e[1]:
return True
return False
def main():
result = []
for i in org:
if has_element(result, i):
continue
c = count_element(org, i)
resi = (c, i[0], i[1])
result += [resi]
print(org)
print(result)
if __name__ == '__main__':
main()
Similar to the other answers, but for any tuple dimension:
org = [(12, 4), (8, 4), (12, 8), (12, 8), (4, 3, 2, 1)]
from collections import Counter
[(count,) + item for item, count in Counter(org).items()]
# [(2, 12, 8), (1, 12, 4), (1, 4, 3, 2, 1), (1, 8, 4)]
Counter
is definitely very useful (and idiomatic) for this, but it's good to remember that it's easy to construct a similar structure with a plain dict
:
counter = dict()
for item in org:
if item not in counter:
counter[item] = 1
else:
counter[item] += 1
# Alternatively, just: counter[item] = counter.get(item, 0) + 1
Its properties are ideal for this task. If you're not familiar with dict
s, more amazement is awaiting you. :)
Using a combination of a Counter and a list comprehension, we can do this fairly quickly. It will result in a new tuple though, since a tuple is immutable.
from collections import Counter
org = [ ( 12, 4 ),
( 8, 4 ),
( 12, 8 ),
( 12, 8 ) ]
counts = Counter(org)
org_counts = [(counts[o], o[0], o[1]) for o in set(org)]
The org_count
variable looks like this at the end of the script:
[(2, 12, 8), (1, 12, 4), (1, 8, 4)]
It's important to note that the Counter
is a dictionary subclass, thus unordered. That means you final list can be in a different order than the original org
variable. I made the assumption that this was alright, because duplicates would be compressed into a single entry, thus messing up the order.
In the list comprehension, I utilize the unique set
of org
to prevent duplicate entries.
for o in set(org)
An easier way to do what you are doing would be to use collections.Counter
and list comprehension -
import collections
def main()
result = [(v,) + k for k,v in collections.Counter(org).items()]
print(org)
print(result)
Please note, this would not preserve the order from the original list.
Demo -
>>> org = [ ( 12, 4 ),
... ( 8, 4 ),
... ( 12, 8 ),
... ( 12, 8 ) ]
>>>
>>> result = [(v,) + k for k,v in collections.Counter(org).items()]
>>> result
[(2, 12, 8), (1, 12, 4), (1, 8, 4)]
If you want to preserve the order, I would suggest you use a set to record the elements that are already seen and use collections.Counter()
for counting. Example -
import collections
def main():
result = []
seen = set()
counts = collections.Counter(org)
for x in org:
if x not in seen:
result.append((counts[x],) + x)
seen.add(x)
Demo -
>>> org
[(12, 4), (8, 4), (12, 8), (12, 8)]
>>>
>>> result = []
>>> seen = set()
>>> counts = collections.Counter(org)
>>> for x in org:
... if x not in seen:
... result.append((counts[x],) + x)
... seen.add(x)
...
>>> result
[(1, 12, 4), (1, 8, 4), (2, 12, 8)]
Also, just a suggestion , a better way to do the following -
def has_element(look_in, e):
"""
'look_in' is a three-element tuple
'e' is a two-element tuple
"""
for x, y, z in look_in:
if y == e[0] and z == e[1]:
return True
return False
Is to use any()
, Example -
def has_element(look_in, e):
"""
'look_in' is a three-element tuple
'e' is a two-element tuple
"""
return any(y == e[0] and z == e[1] for _, y, z in look_in)
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.