Sorting Lists by Repetitions in Python - python

I have a list that contains multiple repeated items. I'm trying to sort the list by giving items with the most repetitions priority.
So it would turn this
['a', 'b', 'c', 'a', 'b', 'a', 'd']
into this
['a', 'a', 'a', 'b', 'b', 'c', 'd']

>>> from collections import Counter
>>> [k for k,v in Counter(['a', 'b', 'c', 'a', 'b', 'a', 'd']).most_common() for i in xrange(v)]
['a', 'a', 'a', 'b', 'b', 'c', 'd']
This is possibly easier to follow
>>> counter = Counter(['a', 'b', 'c', 'a', 'b', 'a', 'd'])
>>> sorted(counter.elements(), key=counter.get, reverse=True)
['a', 'a', 'a', 'b', 'b', 'c', 'd']

d = {}
for a in l:
d[a] += d.setdefault(a,0)
l.sort(key = lambda k: (d[k],k), reverse = True)

[v for (v, c) in sorted(((x, list(y)) for (x, y) in
itertools.groupby(sorted(['a', 'b', 'c', 'a', 'b', 'a', 'd']))),
key=lambda x: len(x[1]), reverse=True) for z in c]
EDIT:
Now with sum()!
sum((c for (v, c) in sorted(((x, list(y)) for (x, y) in
itertools.groupby(sorted(['a', 'b', 'c', 'a', 'b', 'a', 'd']))),
key=lambda x: len(x[1]), reverse=True)), [])

l = ['a', 'b', 'c', 'a', 'b', 'a', 'd']
sorted_list = [item for item in sorted(l, key=lambda x: l.count(x), reverse=True)]
While this is a simple solution, mind the complexity of counting every element when using large lists.

Related

How can copy string in the list?

I have a list
list1=['a','b','c]
I wnat to copy every string in the list
like this
list2=['a','a','b','b','c','c']
list3=['a','a','a','b','b','b','c','c','c']
but when I use this code
list2=[x*2 for x in list1]
I get
list2=['aa','bb','cc]
How can I change my code to accomplish my result?
I would use itertools.chain along with itertools.repeat:
from itertools import chain, repeat
chars = ['a', 'b', 'c']
repeat_count = 3
list(chain.from_iterable(repeat(char, repeat_count) for char in chars))
Output:
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']
without using itertools, this could be done with nested list comprehension like below
list1=['a','b','c']
print([y for x in list1 for y in [x]*2])
# ['a', 'a', 'b', 'b', 'c', 'c']
print([y for x in list1 for y in [x]*3])
# ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']
You can use the second for loop with the function range():
lst = ['a', 'b', 'c']
[i for i in lst for _ in range(2)]
# ['a', 'a', 'b', 'b', 'c', 'c']

Create combinations from a list and 3 ranges using itertools

I have the following:
a_list = [A,B,C]
r1 = range(1,5)
r2 = range(1,5)
r3 = range(1,5)
I would like to be able to find the various combinations of the elements in this list against the ranges. For example:
combi1 = [A, B, C, C, C]
combi2 = [A, A, B, C, C]
combi3 = [A, A, A, B, C]
combi4 = [A, B, B, C, C]
Etc.
I am able to do so if there were only 2 range, but I'm not sure how to fit 3 range in.
inc = range(1, 5)
desc = range(5, 1, -1)
combis = [list(itertools.chain(*(itertools.repeat(elem, n) for elem, n in zip(list, [i,j])))) for i,j in zip(inc,desc)]
SOLUTION:
def all_exist(avalue, bvalue):
return all(any(x in y for y in bvalue) for x in avalue)
combins = itertools.combinations_with_replacement(a_list, 5)
combins_list = [list(i) for i in combins]
for c in combins_list:
if all_exist(a_list, c) == True:
print c
output:
['A', 'A', 'A', 'B', 'C']
['A', 'A', 'B', 'B', 'C']
['A', 'A', 'B', 'C', 'C']
['A', 'B', 'B', 'B', 'C']
['A', 'B', 'B', 'C', 'C']
['A', 'B', 'C', 'C', 'C']
#doyz. I think this is may be what you are looking for :
From a list abc = ['A','B','C'], you want to obtain its various combinations with replacement. Python has built-in itertools to do this.
import itertools
abc = ['A', 'B', 'C'];
combins = itertools.combinations_with_replacement(abc, 5);
combins_list = [list(i) for i in combins];
print(combins_list[0:10]);
This is the first 10 combinations with replacement :
[['A', 'A', 'A', 'A', 'A'], ['A', 'A', 'A', 'A', 'B'], ['A', 'A', 'A', 'A', 'C'], \
['A', 'A', 'A', 'B', 'B'], ['A', 'A', 'A', 'B', 'C'], ['A', 'A', 'A', 'C', 'C'], \
['A', 'A', 'B', 'B', 'B'], ['A', 'A', 'B', 'B', 'C'], ['A', 'A', 'B', 'C', 'C'], ['A', 'A', 'C', 'C', 'C']]
If you want to include all elements in abc, here is one way, that also includes the permutations :
import itertools
abc = ['A', 'B', 'C'];
combins = itertools.combinations_with_replacement(abc, 5);
combins_list = list(combins);
combins_all =[];
for i in combins_list:
if len(set(i))==len(abc):
combins_all.append(i);
print(combins_all);
include_permutations=[];
for i in combins_all:
permut = list(itertools.permutations(i));
include_permutations.append(permut);
print(include_permutations);
Is this okay?
*Note : itertools.combinations_woth_replacement and itertools.permutations do not result in a list, or tuple, but a different object itself, so you can't treat it as those.

using lambda or list comprehesion to create list with loop

for the following code, how I can write into one line using lambda function or using python list comprehension?
def f():
lst=[]
for i in range(1, 101):
if i < 50:
lst.append('A')
else:
lst.append('B')
return lst
You can use a ternary conditional in a list comprehension:
lst = ['A' if i < 50 else 'B' for i in range(1, 101)]
Note that your function outputs 49 'A's and 51 'B's. I'm not sure if that's intentional.
The easiest way to get 50/50 would be :
['A'] * 50 + ['B'] * 50
If you want to define a lambda:
>>> a_or_b = lambda x: 'AB'[x>50]
>>> [a_or_b(x) for x in range(1,101)]
['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']
As a one-liner :
['AB'[x>50] for x in range(1,101)]
or
['AB'[x>=50] for x in range(100)]
Those comprehensions use the fact that False is 0 and True is 1, and that 'AB'[0] is 'A' and 'AB'[1]is'B'`.
The code, mirroring yours, would be like this:
def f():
return ['A' if i < 50 else 'B' for i in range(1,101)]

Python - finding same elements in three lists (ignoring empty list)

I was wodnering if there was any way to find the common elements of three lists, whilst ignoring a list that is empty among the three.
For example I know that:
a = ['a', 'b', 'c', 'd']
b = ['a', 'v', 'd', 'g']
v = ['d']
>>> set(a).intersection(b, v)
{'d'}
but I was wondering if there was a way to do this:
a = ['a', 'b', 'c', 'd']
b = ['a', 'v', 'd', 'g']
v = []
>>> comparison_method(a, b, v)
{'a', 'd'}
Or if 2 out of 3 lists were empty, it would just return the list that wasn't.
Using filter and then set intersection:
set.intersection(*map(set,filter(None, [a,[],[]])))
O/P: set(['a', 'c', 'b', 'd'])
set.intersection(*map(set,filter(None, [a,b,[]])))
O/P: set(['a', 'd'])
set.intersection(*map(set,filter(None, [a,b,v])))
O/P : set(['d'])
As jme suggested which is a more better solution
set.intersection(*(set(x) for x in [a, b, v] if x))
Just filter out all the list that have len (i.e. length is not zero) and use set-intersection-
>>>a = ['a', 'b', 'c', 'd']
>>>b = ['a', 'v', 'd', 'g']
>>>v=[]
>>>input_list = [a,v,b]
>>>result = reduce(set.intersection,map(set,filter(len,input_list)))
>>>set(['a', 'd'])
Sure, very similar to this, but just filter out the empty lists before running the intersection test:
def comparison_method(*args):
sets = [set(arg) for arg in args if arg]
if not sets:
return []
result = sets[0]
for s in sets[1:]:
result = result.intersection(s)
return result
a = ['a', 'b', 'c', 'd']
b = ['a', 'v', 'd', 'g']
v = []
>>> comparison_method(a, b, v)
{'a', 'd'}

Find the same elements from two lists and print the elements from both lists

There are two lists:
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l = ['a', 'c', 'e']
I want to find the same elements from these two lists, that is:
['a', 'c', 'e']
then I want to print out the element we found, for example, 'a' from both lists, that is: ['a', 'a', 'a'].
The result I want is as follows:
['a', 'a', 'a', 'c', 'c', 'c', 'e', 'e']
I try to doing in this way:
c = []
for item_k in k:
for item_j in j:
if item_k== item_j:
c.append(item_k)
c.append(item_j)
However, the result is ['a', 'a', 'c', 'c', 'e', 'e']
Also in this way:
c=[]
for item_k in k:
if item_k in l:
c.append(item_k)
d=l.count(item_k)
c.append(item_k*d)
print c
But it do not works, can anybody tell me how to do it? really appreciate your help in advance
result = [x for x in sorted(k + l) if x in k and x in l]
print(result)
results:
['a', 'a', 'a', 'c', 'c', 'c', 'e', 'e']
Since you want to pick up elements from both lists, the most straight forward way is probably to iterate over both while checking the other one (this is highly optimizatiable if you depend on speed for doing this):
merged = []
for el in list1:
if el in list2:
merged.append(el)
for el in list2:
if el in list1:
merged.append(el)
.. if the order of the elements is important, you'll have to define an iteration order (in what order do you look at what element from what array?).
If the lists are sorted and you want the result to be sorted:
sorted([x for x in list1 if x in set(list2)] + [x for x in list2 if x in set(list1)] )
You can use set operations to intersect and then loop through, appending to a new list any that match the intersected list
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l = ['a', 'c', 'e']
common_list = list(set(k).intersection(set(l)))
all_results = []
for item in k:
if item in common_list:
all_results.append(item)
for item in l:
if item in common_list:
all_results.append(item)
print sorted(all_results)
output:
['a', 'a', 'a', 'c', 'c', 'c', 'e', 'e']
Here's a compact way. Readability might suffer a little, but what fun are comprehensions without a little deciphering?
import itertools
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l = ['a', 'c', 'e']
combined = [letter for letter in itertools.chain(k,l) if letter in l and letter in k]
Here is an implementation that matches your initial algorithm:
k = ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'e']
l=['a', 'c', 'e']
c=[]
for x in l:
count = 0
for y in k:
if x == y:
count += 1
while count>=0:
c.append(x)
count = count -1
print c

Categories

Resources