Python: Get all combinations of sequential elements of list - python

Given an array say x = ['A','I','R']
I would want output as an
[['A','I','R'],['A','I'],['I','R'],['A'],['I'],['R']]
What I don't want as output is :
[['A','I','R'],['A','I'],['I','R'],['A','R'],['A'],['I'],['R']] # extra ['A','R'] which is not in sequence .
Below is the code which gives the output I don't want:
letter_list = [a for a in str]
all_word = []
for i in xrange(0,len(letter_list)):
all_word = all_word + (map(list, itertools.combinations(letter_list,i))) # dont use append. gives wrong result.
all_word = filter(None,all_word) # remove empty combination
all_word = all_word + [letter_list] # add original list
My point is I only want combinations of sequences. Is there any way to use itertools or should I write custom function ?

Yes, you can use itertools:
>>> x = ['A', 'I', 'R']
>>> xs = [x[i:j] for i, j in itertools.combinations(range(len(x)+1), 2)]
>>> xs
[['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
>>> sorted(xs, key=len, reverse=True)
[['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]
Credit: answer by hochl

Try to use yield:
x = ['A','I','R']
def groupme(x):
s = tuple(x)
for size in range(1, len(s) + 1):
for index in range(len(s) + 1 - size):
yield list(x[index:index + size])
list(groupme(x))
>>> [['A'], ['I'], ['R'], ['A', 'I'], ['I', 'R'], ['A', 'I', 'R']]

don't try to be so magical: two loops will do what you want; one over possible sequence starts, the inner over possible sequence lengths:
x = "AIR" # strings are iterables/sequences, too!
all_words = []
for begin in xrange(len(x)):
for length in xrange(1,len(x) - begin+1):
all_words.append(x[begin:begin+length])

using list comprehension:
letters=['A', 'I', 'R']
[letters[start:end+1]
for start in xrange(len(letters))
for end in xrange(start, len(letters))]
[['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
if it is important to have the order you proposed (from longest to shortest and when the same length by starting position) you can do instead:
[letters[start:start+l+1]
for l in range(len(letters))[::-1]
for start in xrange(len(letters)-l)]
[['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]
Just to address Holroy comment. If instead of using list comprehension you use a generator expression (just substituting external [] with ()) you would get a much less memory requiring code. But in this case you must be careful of not using the result more than once or for instance not trying to use list methods (such as len, or removing elements) on the result.

Related

Python recursion systematic ordering

I wrote my code and it's working perfectly but the output doesn't really look good. I was it to look more presentable/systematic. How do I do that? This is the kind of result I'm currently getting:
and this is the type of result I want:
This code is basically to find permutations of whatever is inputted.
def permutations(aSet):
if len(aSet) <= 1: return aSet
all_perms = []
first_element = aSet[0:1]
subset = aSet[1:]
partial = permutations(subset)
for permutation in partial:
for index in range(len(aSet)):
new_perm = list(permutation[:index])
new_perm.extend(first_element)
new_perm.extend(permutation[index:])
all_perms.append(new_perm)
return all_perms
I can't figure out what to try.
You can sort the output array with a custom key function. Here keyFunc converts a permutaiton (list of characters) into a single string to perform lexicographic sorting.
from pprint import pprint
# insert your function here
def keyFunc(char_list):
return ''.join(char_list)
chars = list('dog')
permutation = permutations(chars)
permutation.sort(key=keyFunc)
pprint(permutation)
Output:
[['d', 'g', 'o'],
['d', 'o', 'g'],
['g', 'd', 'o'],
['g', 'o', 'd'],
['o', 'd', 'g'],
['o', 'g', 'd']]
Here's a way to order the permutations differently: for each item in the input array, take it out of the array, find all permutations of the remaining subarray, then prepend this item to each permutation of this subarray. This has the effect of placing permutations with similar prefixes together.
from pprint import pprint
def permutations2(chars):
if len(chars) <= 1: return [chars]
all_perms = []
for idx, char in enumerate(chars):
subarr = chars[:idx] + chars[idx+1:]
subperms = permutations2(subarr)
for subperm in subperms:
new_perm = [char] + subperm
all_perms.append(new_perm)
return all_perms
chars = list('dog')
pprint(permutations2(chars))
Result:
[['d', 'o', 'g'],
['d', 'g', 'o'],
['o', 'd', 'g'],
['o', 'g', 'd'],
['g', 'd', 'o'],
['g', 'o', 'd']]

Removes duplicates from nested list without use of set

I have a list of lists and I want to remove duplicates within each nested list.
Input: [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
Output: [['c', 'p'], ['a'], ['t','p']]
The key here is that I cannot use the set() function or fromkeys().
Here is the code I have,
ans = []
for i in letters:
[ans.append([x]) for x in i if x not in ans]
which returns
[['c'], ['p'], ['p'], ['a'], ['a'], ['a'], ['t'], ['t'], ['p']]
which isn't what I want.
You tripped yourself up with the nested lists. A second loop is necessary to filter the elements. Although it's quite inefficient, you can write your attempt as
ans = []
for i in letters:
k = []
for j in i:
if j not in k:
k.append(j)
ans.append(k)
You can likely shorten this code, but not reduce its complexity.
To do that, you can use something sorted and itertools.groupby. this is still less efficient than a hash table, but better than linear lookup (although it likely doesn't matter much for short arrays):
ans = [[k for k, _ in groupby(sorted(i))] for i in letters]
You can iterate over the inner list and check if that character is already present or not
inputList = [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
result = []
for l in inputList:
# create a empty list to store intermediate result
tmp = []
# iterate over sublist
for ch in l:
if ch not in tmp: tmp.append(ch)
result.append(tmp)
print(result)
Since you can't use set() or fromkeys(), I would suggest a normal loop iteration, each time checking if value is already present:
lst = [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
new_lst = []
for x in lst:
res = []
for y in x:
if y not in res:
res.append(y)
new_lst.append(res)
print(new_lst)
Ideally, new_lst here should be a set.
list=[['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
ans=[]
for sublist in list:
temp=[]
for ch in sublist:
if ch not in temp:
temp.append(ch)
ans.append(temp)
print(ans)
#I think it should work, very simple, it could be more complex
Just ignore every instance of a letter until it is the last one.
for every sublist of input:[[...] for sub in input]
store the letter if it isn't in the rest of the sublist:[ltr for i, ltr in enumerate(sub) if ltr not in sub[i+1:]]
Put it together and you have:
input = [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
output = [[ltr for i, ltr in enumerate(sub) if ltr not in sub[i+1:]] for sub in input]
print(output) #[['c', 'p'], ['a'], ['t', 'p']]

Search for a char in list of lists

I have a list of lists, and I want to return those sublists that have a specific char.
If the list is:
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
I want to retrive ['g', 'j'] "or it's position" if I search using j or g
Try this:-
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def search(search_char):
result = [x for x in lst if search_char in x]
return result
print(search('g'))
For a start there is a keyword error in your variable - list is a keyword, try my_list.
This works for returning the list you want:
#Try this
my_list = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def check_for_letter(a_list,search):
for i in a_list[:]:
if search in a_list[0]:
return a_list[0]
else:
a_list[0] = a_list[1]
Session below:
>>> check_for_letter(my_list,"j")
['g', 'j']
>>>
This is one way. It works even for repeats.
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def searcher(lst, x):
for i in range(len(lst)):
if x in lst[i]:
yield i
list(searcher(lst, 'g')) # [1]
list(map(lst.__getitem__, searcher(lst, 'g'))) # [['g', 'j']]
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
spec_char = input("What character do you want to find?: ")#ask for a character to find
def find_char(spec_char):
for list_count, each_list in enumerate(lst): #iterates through each list in lst
if spec_char in each_list: #checks if specified character is in each_list
return spec_char, lst[list_count] #returns both the character and list that contains the character
def main(): #good habit for organisation
print(find_char(spec_char)) #print the returned value of find_char
if __name__ == '__main__':
main()
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def search(spec_char):
for subList in lst:
if spec_char in subList:
return subList
return False
print search('g')
>>> ['g', 'j']
y=[['a','b'],['c','d'],['e','f'],['f']]
result=[x for x in y if 'f' in x])
here I took 'f' as the character to be searched
Alternatively, we can also use the lambda and the filter functions.
The basics for lambda and filter function can be found in python documentation.
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
ch = input('Enter the character') # or directly type the character in ''
# lambda <parameter to the function>: <value to be returned>
# filter(<lambda function to check for the condition>, <sequence to iterate over>)
r = list(filter(lambda lst: ch in lst,lst))
print(r)
Note: To see the value returned by the lambda and the filter functions, I am storing the result in a list and printing the final output.
Below is the solution and explanation for your question. Please view the image at the bottom of this answer for further clarification and to view the output.
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']] #So this is your list
character=input("Enter the character: ") #The character you are searching for
for a in lst: #it means that variable [a] is an item in the list [lst]
for b in a: #it means that variable [b] is an item in the list [a]
if(b==character): #To check if the given character is present in the list
print(a) #Finally to print the list in which the given character is present
So, the code part is over. Now, let's look what the output will be.
C:\Users\User\Desktop\python>coc.py
Enter the character: a
['a', 'e']
C:\Users\User\Desktop\python>coc.py
Enter the character: w
['m', 'n', 'w']
Click here to view the image of my code and output

Python merging sublist

I've got the following list :
[['a','b','c'],['d','e'],['f','g','h','i',j]]
I would like a list like this :
['abc','de','fghij']
How is it possible?
[Edit] : in fact, my list could have strings and numbers,
l = [[1,2,3],[4,5,6], [7], [8,'a']]
and would be :
l = [123,456, 7, 8a]
thx to all,
you can apply ''.join method for all sublists.
This can be done either using map function or using list comprehensions
map function runs function passed as first argument to all elements of iterable object
initial = ['a', 'b', 'c'], ['d', 'e'], ['f', 'g', 'h', 'i', 'j']]
result = map(''.join, initial)
also one can use list comprehension
initial = ['a', 'b', 'c'], ['d', 'e'], ['f', 'g', 'h', 'i', 'j']]
result = [''.join(sublist) for sublist in initial]
Try
>>> L = [['a','b','c'],['d','e'],['f','g','h','i','j']]
>>> [''.join(x) for x in L]
['abc', 'de', 'fghij']

Multi-item sort based with two different list items and reorder/reshuffle?

I have a nested list that looks like this:
li = [['m', 'z', 'asdgwergerwhwre'],
['j', 'h', 'asdgasdgasdgasdgas'],
['u', 'a', 'asdgasdgasdgasd'],
['i', 'o', 'sdagasdgasdgdsag']]
I would like to sort this list alphabetically, BUT using either the first or second element in each sublist. For the above example, the desired output would be:
['a', 'u', 'asdgasdgasdgasd']
['h', 'j', 'asdgasdgasdgasdgas']
['i', 'o', 'sdagasdgasdgdsag']
['m', 'z', 'asdgwergerwhwre']
What is the best way to achieve this sort?
As the first step we perform some transformation (swap for first two items - if needed) and at the second aplly simple sort:
>>> sorted(map(lambda x: sorted(x[:2]) + [x[2]], li))
[['a', 'u', 'asdgasdgasdgasd'],
['h', 'j', 'asdgasdgasdgasdgas'],
['i', 'o', 'sdagasdgasdgdsag'],
['m', 'z', 'asdgwergerwhwre']]
You can make use of the built-in method sorted() to accomplish some of this. You would have to reverse the order of the list if you wanted to reverse the way it was printed, but that's not too difficult to do.
def rev(li):
for l in li:
l[0], l[1] = l[1], l[0]
return li
new_list = sorted(rev(li))
If you wanted to sort the list based on a specific index, you can use sorted(li, key=lambda li: li[index]).
import pprint
li = [['m', 'z', 'asdgwergerwhwre'],
['j', 'h', 'asdgasdgasdgasdgas'],
['u', 'a', 'asdgasdgasdgasd'],
['i', 'o', 'sdagasdgasdgdsag']]
for _list in li:
_list[:2]=sorted(_list[:2])
pprint.pprint(sorted(li))
>>>
[['a', 'u', 'asdgasdgasdgasd'],
['h', 'j', 'asdgasdgasdgasdgas'],
['i', 'o', 'sdagasdgasdgdsag'],
['m', 'z', 'asdgwergerwhwre']]

Categories

Resources