How to count in a row results from text file - python

i would like to know how to count in a row results from text file. I wroted this code:
from itertools import groupby
def count_runs_of(seq, val):
return sum(key == val for key, group in groupby(seq))
Example:
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 3)
1
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
2
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3, 9, 2, 4, 3, 3, 3], 3)
3
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 2)
2
I want to know how long serie it is. For example, when i have "1" in first result, i want to also print "3" (because there was 3 x 3 in a row). Could You help me? Thank You

def count_runs_of(seq, val):
return [len(list(group)) for key, group in groupby(seq) if key == val]
Example
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
[3, 2]

You were pretty close, you get get the length of a group by looping on it using sum() and generator expression. This will return length of all such runs in the list:
>>> def count_runs_of(seq, val):
return [sum(1 for _ in g) for k, g in groupby(seq) if k == val]
...
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 3)
[3]
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
[3, 2]

Related

Python: How to aggregate and count identical values in a Dictionary

I'm using a defaultdict from Python's collections:
from collections import defaultdict
data = defaultdict(list)
Within the dictionary I have a set of key/list. Example:
{1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]})
I'm looking for a way to count how many times each list (identical order and content) is found in the dictionary. Basically, I need to aggregate each list with a counter.
For example, the combination [1, 6, 3, 4, 5] is found 2 times.
Is there any helper class/function that can do it? Other than that, I'd just create a double for loop across the dictionary.
Thanks!
Try this:
from collections import Counter
data = defaultdict(list, {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]})
c = Counter(map(tuple, data.values()))
print(c)
Counter({(1, 6, 3, 4, 5): 2, (1, 3, 2, 4, 5): 1})
H = {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]}
occurences = dict()
for i in H.keys() :
k = 0
for j in H.keys():
if H[j] == H[i] :
k += 1
if i not in occurences.keys():
occurences[i] = k
Use collections.Counter
>>> from collections import Counter
>>> d = {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]}
>>> print(Counter(tuple(l) for l in d.values())
Counter({(1, 6, 3, 4, 5): 2, (1, 3, 2, 4, 5): 1})
You'll have to convert your lists to tuples, because Counters can't count unhashable (mutable) types.

How can I select a specific number in a list with duplicates without removing the previous same values?

I have the following list in python3:
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
I want to have something like this as an output:
b = [1, 2, 3, 1, 2, 4, 3]
How can I do that? I have tried a = set(a) and other methods for getting rid of duplicates. But they remove all duplicates.
If you are willing to use a module, you can use itertools.groupby:
from itertools import groupby
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
output = [k for k, _ in groupby(a)]
print(output) # [1, 2, 3, 1, 2, 4, 3]
This would work:
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
b = [a[0]]
for k in a:
if k!=b[-1]:
b.append(k)
print(b)
If you comfortable with C, you may like this style:
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
b=len(a)
i=0
last_one=None
while i<b:
if a[i]==last_one:
del a[i]
b-=1
continue
else:
last_one=a[i]
i+=1
print(a)

Get counters within cycles

Say I have a list as follows:
list_sequences = [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 3, 1]
I want to create another list with the count of the occurrences, but the occurrence of 2 and 3 is reset after an occurrence of 1.
Something like:
occurrence_list = [1, 1, 1, 2, 2, 2, 1, 1, 3, 1, 1, 2, 2, 3, 3, 4, 4, 4]
is there a simple pythonic way to do so?
You can use a defaultdict to keep account of what is going on:
from collections import defaultdict
list_sequences = [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 3, 1]
def make_occurrence(seq):
counter = defaultdict(int)
occurrence = []
for item in seq:
count = counter[item] + 1
if item == 1:
counter.clear()
counter[item] = count
occurrence.append(count)
return occurrence
print(make_occurrence(list_sequences))
Output as requested

recursively split list into sub lists based on first element length

I am breaking my head around this small issue which I am sure can (and should) be solved recursively.
# split list in sublists based on length of first element.
list = [3, 1, 2, 3, 4, 1, 2, 3, 4]
#* #*
# *number of elements of the sublist
It is better shown than explained, the above should result to:
[[1, 2, 3], [1, 2, 3, 4]]
The lists I am processing always respect this logic, the first element is always the length of the following n elements.
EDIT:
Based on some of the suggestions, I simply added a yield to get it done lazily.
def split(ls):
"""
func that given a list extracts sub lists with the length indicated by the first element
[2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4] => [[1, 2], [1, 2, 3], [1, 2, 3, 4]]
"""
res = []
while ls:
dim = ls[0]
yield ls[1:dim + 1]
ls = ls[dim + 1:]
return res
>>> list(split([2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4]))
[[1, 2], [1, 2, 3], [1, 2, 3, 4]]
Simple slicing will do:
>>> a = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> c = []
>>> while len(a) :
... b = a[0]
... c.append( a[1:b+1] )
... a = a[b+1:]
...
>>> c
[[1, 2, 3], [1, 2, 3, 4]]
Here is a way to achieve what you want:
numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4]
result = []
def split_list(list_):
first = list_.pop(0)
result.append(list_[:first])
if len(list_[first:]) > 0:
split_list(list_[first:])
split_list(numbers)
print(result)
You can use itertools.islice here.
>>> from itertools import islice
>>> lst = [3, 1, 2, 3, 4, 1, 2, 3, 4]
>>> def chunks(lst):
... t=iter(lst)
... c=next(t,None)
... while c:
... yield list(islice(t,None,c))
... c=next(t,None)
...
>>> list(chunks(lst))
[[1, 2, 3], [1, 2, 3, 4]]
I've edited my answer as inspired by someone else's in this thread. This doesn't consume the original array and uses recursion instead of looping.
numbers = [3, 1, 2, 3, 4, 1, 2, 3, 4, 3,1,1,1,1]
def do_take(numbers: []):
result = []
to_take = numbers[0]
result.append(numbers[1:to_take + 1])
if len(numbers) > to_take:
result.append(do_take(numbers[to_take + 1:]))
return result
print(do_take(numbers))
print(numbers)
Results in the following output:
# python /tmp/breakup.py
[[1, 2, 3], [[1, 2, 3, 4], [[1, 1, 1], [[]]]]]
[3, 1, 2, 3, 4, 1, 2, 3, 4, 3, 1, 1, 1, 1]

Combinations with limited repeats in Python

I know how to get ALL combinations of a list in Python with itertools, but what if I want to limit the amount of repeats?
So, if I have [1, 2, 3, 4, 5]
But I want to limit combinations to only 3 repeats of each item (with a fixed length of the final list, say 10):
[1, 1, 1, 2, 3, 3, 5, 5, 5, 4]
[1, 2, 3, 3, 3, 4, 5, 5, 4, 4]
[4, 4, 1, 1, 1, 5, 2, 2, 2, 3]
and so on. How do I do this?
This would work:
import random
L = [1, 2, 3, 4, 5]
L3 = L * 3
random.shuffle(L3)
L3[:10]
I don't know if there is a more elegant way but that seems to work:
from itertools import combinations_with_replacement
a = [1, 2, 3, 4, 5] # can contain letters as well
all_combinations = combinations_with_replacement(a, 10)
filtered_results = []
for current in all_combinations:
throw_away = False
for item in current:
if current.count(item) > 3:
throw_away = True
break
if not throw_away:
filtered_results.append( current )
for j in filtered_results:
print(j)
You could do it the following way: Use [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5] and use itertools.combination(the list from above, 10). That would mean that each element occurs at most three times in a resulting list.
Example with smaller list:
Edited to ensure every combination occurs exactly once, the combinations occur in random order and, finally, every combination has a random order.
Also incorporated the idea of Mike Müller to just multiply the list by 3.
import itertools
import random
combinations = set()
for c in itertools.combinations(sorted([1, 2, 3] * 3), 5):
combinations.add(c)
shuffledCombinations = list(combinations)
random.shuffle(shuffledCombinations)
for combination in shuffledCombinations:
copiedCombination = list(combination)
random.shuffle(copiedCombination)
print copiedCombination
which will give:
[2, 1, 3, 2, 2]
[2, 2, 1, 1, 2]
[3, 3, 3, 1, 2]
[2, 2, 3, 2, 3]
[1, 2, 3, 1, 2]
[1, 1, 1, 2, 3]
[2, 1, 1, 1, 2]
[3, 3, 1, 1, 1]
[1, 3, 3, 3, 1]
[3, 2, 3, 2, 3]
[3, 2, 1, 2, 3]
[1, 1, 2, 3, 3]

Categories

Resources