I have a list:
listvalue = ['charity','hospital','carrefour']
I tried to concat two index from a list:
twoconcat = [listvalue[i:i + 2] for i in range(len(listvalue))]
The output I am getting is:
[['charity', 'hospital'], ['hospital', 'carrefour'], ['carrefour']]`
I want the output to be
[['charity','hospital'],['charity','carrefour'],['hospital','charity'],['hospital','carrefour'],['carrefour','charity'],['carrefour','hospital']]
Any suggestions?
You can do this using itertools.permutations.
>>> places = ['charity','hospital','carrefour']
>>> list(itertools.permutations(places, 2))
[('charity', 'hospital'), ('charity', 'carrefour'), ('hospital', 'charity'),
('hospital', 'carrefour'), ('carrefour', 'charity'), ('carrefour', 'hospital')]
If you do not care about list comprehension. This can be helpful,
runs on python 2.x
listvalue = ['charity','hospital','carrefour']
arr_len= len(listvalue)
result=[]
for i in range(arr_len):
for j in range(arr_len):
if i !=j:
result.append([listvalue[i],listvalue[j]])
print result
result
[['charity', 'hospital'], ['charity', 'carrefour'], ['hospital', 'charity'], ['hospital', 'carrefour'], ['carrefour', 'charity'], ['carrefour', 'hospital']]
l = ['a', 'b', 'c']
[[x, y] for x in l for y in l if y != x]
Output :
[['a', 'b'], ['a', 'c'], ['b', 'a'], ['b', 'c'], ['c', 'a'], ['c', 'b']]
#Alasdair is right...use itertools.
Code:
from itertools import permutations
places = ['charity','hospital','carrefour']
result = list(permutations(places, 2)
Output:
[('charity', 'hospital'), ('charity', 'carrefour'), ('hospital', 'charity'), ('hospital', 'carrefour'), ('carrefour', 'charity'), ('carrefour', 'hospital')]
Code:
from itertools import permutations
places = ['charity','hospital','carrefour']
result = [list(place) for place in list(permutations(places, 2))]
Output:
[['charity','hospital'],['charity','carrefour'],['hospital','charity'],['hospital','carrefour'],['carrefour','charity'],['carrefour','hospital']]
Related
how can I extract for example [['A', '123'], ['A', '456']] from mylist if I filtered by 'A'?
mylist = [['A', '123'],
['A', '456'],
['B','847'],
['B','677']]
Here are two ways to achieve the results you want.
mylist = [['A', '123'],
['A', '456'],
['B','847'],
['B','677']]
letter = 'A'
# Using list comprehension
print([l for l in mylist if l[0] == letter])
# Using filer function
print(list(filter(lambda l: l[0] == letter, mylist)))
I made a code for you.
mylist = [['A', '123'],
['A', '456'],
['B', '847'],
['B', '677']]
output = [lst for lst in mylist if 'A' in lst]
print(output)
Or you can use this code;
output = [lst for lst in mylist if 'A' == lst[0]]
How can I go from this structure
>>> input = ['a', 'b', 'c']
to this one
>>> output
['a', 'a/b', 'a/b/c']
in an elegant (functional) way?
For now I have this:
>>> from functools import reduce
>>> res = []
>>> for i in range(len(input)):
... res.append(reduce(lambda a, b: a + '/' + b, input[:i+1]))
...
>>> res
['a', 'a/b', 'a/b/c']
You can use itertools.accumulate():
from itertools import accumulate
l = ['a', 'b', 'c']
print(list(accumulate(l, '{}/{}'.format)))
This outputs:
['a', 'a/b', 'a/b/c']
You can do this using a simple list comprehension.
l = ['a', 'b', 'c']
['/'.join(l[:i]) for i in range(1, len(l)+1)]
# ['a', 'a/b', 'a/b/c']
If performance is important, you can roll out your own implementation of accumulate:
out = [l[0]]
for l_ in l[1:]:
out.append('{}/{}'.format(out[-1], l_))
out
# ['a', 'a/b', 'a/b/c']
This turns out to be slightly faster than itertools for the given problem.
This should work:
l = ['a', 'b', 'c']
new_list =[]
for i in range(len(l)):
new_list.append("/".join([a for a in l[:i+1]]))
If you must use reduce you could do it like this:
from functools import reduce
input = ['a', 'b', 'c']
output = [reduce(lambda a, b: f"{a}/{b}", input[:n + 1]) for n in range(0, len(input))]
I prefer the built in join function:
output = ['/'.join(input[:n + 1]) for n in range(0, len(input))]
You can use count to slice a string in steps:
from itertools import count
input = ['a', 'b', 'c']
s = '/'.join(input)
c = count(1, 2)
[s[:next(c)] for _ in input]
# ['a', 'a/b', 'a/b/c']
a recursive solution:
The idea is quite simple, we use divide and conquer.
Problem can be solved if we know the answer to the first n-1 string(or char), in this case, what we need to do is just collect all the characters in one string and separate them by '/'('a/b/c' in this case).
we pass an empty list as the 2nd parameter to store the result.
input = ['a', 'b', 'c']
def foo(list1, list2):
if (len(list1) == 0):
return list2
else:
s = list1[0]
for char in list1[1:]:
s += '/' + char
list2.insert(0, str)
return foo(list1[:-1], list2)
>>> foo(input, [])
['a', 'a/b', 'a/b/c']
So basically for example of you have a list like:
l = ['a','b','a','b','c','c']
The output should be:
[['a','a'],['b','b'],['c','c']]
So basically put together the values that are duplicated into a list,
I tried:
l = ['a','b','a','b','c','c']
it=iter(sorted(l))
next(it)
new_l=[]
for i in sorted(l):
new_l.append([])
if next(it,None)==i:
new_l[-1].append(i)
else:
new_l.append([])
But doesn't work, and if it does work it is not gonna be efficient
Sort the list then use itertools.groupby:
>>> from itertools import groupby
>>> l = ['a','b','a','b','c','c']
>>> [list(g) for _, g in groupby(sorted(l))]
[['a', 'a'], ['b', 'b'], ['c', 'c']]
EDIT: this is probably not the fastest approach, sorting is O(n log n) time complexity for the average case and not required for all solutions (see the comments)
Use collections.Counter:
from collections import Counter
l = ['a','b','a','b','c','c']
c = Counter(l)
print([[x] * y for x, y in c.items()])
# [['a', 'a'], ['b', 'b'], ['c', 'c']]
You can use collections.Counter:
from collections import Counter
[[k] * c for k, c in Counter(l).items()]
This returns:
[['a', 'a'], ['b', 'b'], ['c', 'c']]
%%timeit comparison
Given a sample dataset of 100000 values, this answer is the fastest approach.
Another approach is to use zip method.
l = ['a','b','a','b','c','c','b','c', 'a']
l = sorted(l)
grouped = [list(item) for item in list(zip(*[iter(l)] * l.count(l[0])))]
Output
[['a', 'a', 'a'], ['b', 'b', 'b'], ['c', 'c', 'c']]
Here's a functional solution via itertools.groupby. As it requires sorting, this will have time complexity O(n log n).
from itertools import groupby
from operator import itemgetter
L = ['a','b','a','b','c','c']
res = list(map(list, map(itemgetter(1), groupby(sorted(L)))))
[['a', 'a'], ['b', 'b'], ['c', 'c']]
The syntax is cumbersome since Python does not offer native function composition. This is supported by 3rd party library toolz:
from toolz import compose
foo = compose(list, itemgetter(1))
res = list(map(foo, groupby(sorted(L))))
My solution using list comprehension would be (l is a list):
[l.count(x) * [x] for x in set(l)]
set(l) will retrieve all the element which appears in l, without duplicates
l.count(x) will return the number of times a specific element x appears in a given list l
the * operator creates a new list with the elements in a list (in this case, [x]) repeated the specified number of times (in this case, l.count(x) is the number of times)
l = ['a','b','a','b','c','c']
want = []
for i in set(l):
want.append(list(filter(lambda x: x == i, l)))
print(want)
Probably not the most efficient, but this is understandable:
l = ['a','b','a','b','c','c']
dict = {}
for i in l:
if dict[i]:
dict[i] += 1
else:
dict[i] = 1
new = []
for key in list(dict.keys()):
new.append([key] * dict[key])
So I have a list of lists of strings
[['a','b'],['c','d'],['e','f']]
and I want to get all possible combinations, such that the result is
[['a','b'],['c','d'],['e','f'],
['a','b','c','d'],['a','b','e','f'],['c','d','e','f'],
['a','b','c','d','e','f']]
So far I have come up with this code snippet
input = [['a','b'],['c','d'],['e','f']]
combs = []
for i in xrange(1, len(input)+1):
els = [x for x in itertools.combinations(input, i)]
combs.extend(els)
print combs
largely following an answer in this post.
But that results in
[(['a','b'],),(['c','d'],),(['e','f'],),
(['a','b'],['c','d']),(['a','b'],['e','f']),(['c','d'],['e','f']),
(['a','b'],['c', 'd'],['e', 'f'])]
and I am currently stumped, trying to find an elegant, pythonic way to unpack those tuples.
You can use itertools.chain.from_iterable to flatten the tuple of lists into a list. Example -
import itertools
input = [['a','b'],['c','d'],['e','f']]
combs = []
for i in xrange(1, len(input)+1):
els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
combs.extend(els)
Demo -
>>> import itertools
>>> input = [['a','b'],['c','d'],['e','f']]
>>> combs = []
>>> for i in range(1, len(input)+1):
... els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
... combs.extend(els)
...
>>> import pprint
>>> pprint.pprint(combs)
[['a', 'b'],
['c', 'd'],
['e', 'f'],
['a', 'b', 'c', 'd'],
['a', 'b', 'e', 'f'],
['c', 'd', 'e', 'f'],
['a', 'b', 'c', 'd', 'e', 'f']]
One idea for such a goal is to map integers from [0..2**n-1] where n is the number of sublists to all your target element according to a very simple rule:
Take the element of index k if (2**k)&i!=0 where i runs over [0..2**n-1]. In other word, i has to be read bitwise, and for each bit set, the corresponding element from l is kept. From a mathematical point of view it is one of the cleanest way of achieving what you want to do since it follows very closely the definition of the parts of a set (where you have exactly 2**n parts for a set with n elements).
Not tried but something like that should work:
l = [['a','b'],['c','d'],['e','f']]
n = len(l)
output = []
for i in range(2**n):
s = []
for k in range(n):
if (2**k)&i: s = s + l[k]
output.append(s)
If you don't want the empty list, just replace the relevant line with:
for i in range(1,2**n):
If you want all combinations, you may consider this simple way:
import itertools
a = [['a','b'],['c','d'],['e','f']]
a = a + [i + j for i in a for j in a if i != j] + [list(itertools.chain.from_iterable(a))]
With comprehension lists :
combs=[sum(x,[]) for i in range(len(l)) for x in itertools.combinations(l,i+1)]
Given a string, I want to generate all possible combinations. In other words, all possible ways of putting a comma somewhere in the string.
For example:
input: ["abcd"]
output: ["abcd"]
["abc","d"]
["ab","cd"]
["ab","c","d"]
["a","bc","d"]
["a","b","cd"]
["a","bcd"]
["a","b","c","d"]
I am a bit stuck on how to generate all the possible lists. Combinations will just give me lists with length of subset of the set of strings, permutations will give all possible ways to order.
I can make all the cases with only one comma in the list because of iterating through the slices, but I can't make cases with two commas like "ab","c","d" and "a","b","cd"
My attempt w/slice:
test="abcd"
for x in range(len(test)):
print test[:x],test[x:]
How about something like:
from itertools import combinations
def all_splits(s):
for numsplits in range(len(s)):
for c in combinations(range(1,len(s)), numsplits):
split = [s[i:j] for i,j in zip((0,)+c, c+(None,))]
yield split
after which:
>>> for x in all_splits("abcd"):
... print(x)
...
['abcd']
['a', 'bcd']
['ab', 'cd']
['abc', 'd']
['a', 'b', 'cd']
['a', 'bc', 'd']
['ab', 'c', 'd']
['a', 'b', 'c', 'd']
You can certainly use itertools for this, but I think it's easier to write a recursive generator directly:
def gen_commas(s):
yield s
for prefix_len in range(1, len(s)):
prefix = s[:prefix_len]
for tail in gen_commas(s[prefix_len:]):
yield prefix + "," + tail
Then
print list(gen_commas("abcd"))
prints
['abcd', 'a,bcd', 'a,b,cd', 'a,b,c,d', 'a,bc,d', 'ab,cd', 'ab,c,d', 'abc,d']
I'm not sure why I find this easier. Maybe just because it's dead easy to do it directly ;-)
You could generate the power set of the n - 1 places that you could put commas:
what's a good way to combinate through a set?
and then insert commas in each position.
Using itertools:
import itertools
input_str = "abcd"
for k in range(1,len(input_str)):
for subset in itertools.combinations(range(1,len(input_str)), k):
s = list(input_str)
for i,x in enumerate(subset): s.insert(x+i, ",")
print "".join(s)
Gives:
a,bcd
ab,cd
abc,d
a,b,cd
a,bc,d
ab,c,d
a,b,c,d
Also a recursive version:
def commatoze(s,p=1):
if p == len(s):
print s
return
commatoze(s[:p] + ',' + s[p:], p + 2)
commatoze(s, p + 1)
input_str = "abcd"
commatoze(input_str)
You can solve the integer composition problem and use the compositions to guide where to split the list. Integer composition can be solved fairly easily with a little bit of dynamic programming.
def composition(n):
if n == 1:
return [[1]]
comp = composition (n - 1)
return [x + [1] for x in comp] + [y[:-1] + [y[-1]+1] for y in comp]
def split(lst, guide):
ret = []
total = 0
for g in guide:
ret.append(lst[total:total+g])
total += g
return ret
lst = list('abcd')
for guide in composition(len(lst)):
print split(lst, guide)
Another way to generate integer composition:
from itertools import groupby
def composition(n):
for i in xrange(2**(n-1)):
yield [len(list(group)) for _, group in groupby('{0:0{1}b}'.format(i, n))]
Given
import more_itertools as mit
Code
list(mit.partitions("abcd"))
Output
[[['a', 'b', 'c', 'd']],
[['a'], ['b', 'c', 'd']],
[['a', 'b'], ['c', 'd']],
[['a', 'b', 'c'], ['d']],
[['a'], ['b'], ['c', 'd']],
[['a'], ['b', 'c'], ['d']],
[['a', 'b'], ['c'], ['d']],
[['a'], ['b'], ['c'], ['d']]]
Install more_itertools via > pip install more-itertools.