I have a list like the following:
lst = ['a', 'a', 'a', 'start', 'b', 'end', 'a', 'a','a','start','b','b','b','end','a','a','a','a','start','b','b','end']
and my desired result is to split the list into sublists like this:
[['a', 'a', 'a'], ['start', 'b', 'end'], ['a', 'a','a'],['start','b','b','b','end'],['a','a','a','a'],['start','b','b','end']]
so start and end are keywords, is there anyway you can use .split() by using particular keywords/if it matches?
So far I have made a function which finds the indices of 'start' i.e. starting_ind = [3, 9, 18] and ending_ind = [5, 13, 21] however if I do
temp=[]
for i in range(len(starting_ind)):
x = lst[starting_ind[i]: ending_ind[i]]
temp += x
print(temp)
the result is incorrect.
This solution doesn't require you to calculate indices beforehand:
lst = ['a', 'a', 'a', 'start', 'b', 'end', 'a', 'a', 'a', 'start', 'b', 'b',
'b', 'end', 'a', 'a', 'a', 'a', 'start', 'b', 'b', 'end', 'a', 'a', 'a']
result = []
sublist = []
for el in range(len(lst)):
if lst[el] == 'start':
result.append(sublist.copy())
sublist.clear()
sublist.append(lst[el])
else:
sublist.append(lst[el])
if lst[el] == 'end':
result.append(sublist.copy())
sublist.clear()
if el == len(lst) - 1:
result.append(sublist)
print(result)
The result is:
[['a', 'a', 'a'], ['start', 'b', 'end'], ['a', 'a', 'a'], ['start', 'b', 'b', 'b', 'end'], ['a', 'a', 'a', 'a'], ['start', 'b', 'b', 'end'], ['a', 'a', 'a']]
Here's a possible way to use regular expression to extract the patterns, please check if it's acceptable:
import re
lst = ['a','a','a', 'start','b','end', 'a','a','a', 'start','b','b','b','end', 'a','a','a','a', 'start','b','b','end']
result = []
for e in re.findall('a_[a_]+|start[_b]+_end', '_'.join(lst)):
result.append(e.strip('_').split('_'))
print(result)
Output is as desired:
[['a', 'a', 'a'],
['start', 'b', 'end'],
['a', 'a', 'a'],
['start', 'b', 'b', 'b', 'end'],
['a', 'a', 'a', 'a'],
['start', 'b', 'b', 'end']]
A better way is this:
result = []
for e in re.split(r'(start[_b]+_end)', '_'.join(lst)):
result.append(e.strip('_').split('_'))
print([x for x in result if x != ['']])
Same output
You can write so:
lst = ['a', 'a', 'a', 'start', 'b', 'end',
'a', 'a','a','start','b','b','b','end','a','a','a','a','start','b','b','end']
temp=[]
ind = [0, 3, 6, 9, 14, 18, 22]
for i in range(len(ind)-1):
x = lst[ind[i]: ind[i+1]]
temp.append(x)
print(temp)
and you will get:
[['a', 'a', 'a'], ['start', 'b', 'end'], ['a', 'a', 'a'], ['start', 'b', 'b', 'b', 'end'], ['a', 'a', 'a', 'a'], ['start', 'b', 'b', 'end']]
If you can be certain that your keywords will always appear in pairs, and in the right order (i.e. there will never be a 'start' without an 'end' that follows it, at some point in the list), this should work:
l = ['a', 'a', 'a', 'start', 'b', 'end', 'a', 'a','a','start','b','b','b','end','a','a','a','a','start','b','b','end']
def get_sublist(l):
try:
return l[:l.index('end') + 1] if l.index('start') == 0 else l[:l.index('start')]
except ValueError:
return l
result = []
while l:
sublist = get_sublist(l)
result.append(sublist)
l = l[len(sublist):]
print(result)
Gives the following result:
[['a', 'a', 'a'],
['start', 'b', 'end'],
['a', 'a', 'a'],
['start', 'b', 'b', 'b', 'end'],
['a', 'a', 'a', 'a'],
['start', 'b', 'b', 'end']]
Related
This question already has answers here:
How do I use itertools.groupby()?
(15 answers)
Closed last month.
This is my list:
nab = ['b', 'b', 'a', 'b', 'b', 'b', 'a', 'a', 'a', 'a']
I want to combine the same elements which are adjacent into another list, and if they are not the same, just return the element itself.
The output that I am looking for is:
['b', 'a', 'b', 'a']
I mean:
two 'b' ---> 'b', one 'a' ---> 'a', three 'b' ---> 'b', four 'a' ---> 'a'
I want to know the length of the new list.
Thank you so much #tdelaney, I did it as below:
import itertools
nab = ['B', 'B', 'A', 'B', 'B', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'A', 'A', 'B', 'B', 'A', 'A', 'B', 'A', 'B', 'B', 'B', 'B', 'A']
U = []
key_func = lambda x: x[0]
for key, group in itertools.groupby(nab, key_func):
U.append(list(group))
print(U)
print(len(U))
Output:
[['B', 'B'], ['A'], ['B', 'B'], ['A', 'A', 'A', 'A'], ['B', 'B', 'B'], ['A', 'A'], ['B', 'B'], ['A', 'A'], ['B'], ['A'], ['B', 'B', 'B', 'B'], ['A']]
The issues stems from the output.append(a) on the third line. This program would ideally output 6 unique permutations of the input string, but instead returns 6 of the first result in the recursive loop. I realize exiting the recursion may have something to do with the array being modified, but how can I circumvent this issue to be able to return an array of solutions?
def permute(a, l, r, output):
if l==r:
output.append(a)
else:
for i in range(l,r+1):
a[l], a[i] = a[i], a[l]
permute(a, l+1, r,output)
a[l], a[i] = a[i], a[l] # backtrack
Driver program to test the above function
string = "ABC"
output = []
n = len(string)
a = list(string)
permute(a, 0, n-1,output)
print(output)
For reference, this is what the output looks like:
[['A', 'C', 'B']]
[['B', 'A', 'C'], ['B', 'A', 'C']]
[['B', 'C', 'A'], ['B', 'C', 'A'], ['B', 'C', 'A']]
[['C', 'B', 'A'], ['C', 'B', 'A'], ['C', 'B', 'A'], ['C', 'B', 'A']]
[['C', 'A', 'B'], ['C', 'A', 'B'], ['C', 'A', 'B'], ['C', 'A', 'B'], ['C', 'A', 'B']]
[['A', 'B', 'C'], ['A', 'B', 'C'], ['A', 'B', 'C'], ['A', 'B', 'C'], ['A', 'B', 'C'], ['A', 'B', 'C']]
When the output should be:
['A', 'B', 'C']
['A', 'C', 'B']
['B', 'A', 'C']
['B', 'C', 'A']
['C', 'B', 'A']
['C', 'A', 'B']
The problem is in the line
output.append(a)
it looks fine, but later on the list a changes, and when you append it to output again, the previous a (that you already appended) changes.
To solve the problem, you can simply use shallow copy. Write this instead:
output.append(a[:])
Do you know there is an excisting function in python?
import itertools
listA = ["A", "B", "C"]
perm = itertools.permutations(listA)
for i in list(perm):
print(i)
Result:
('A', 'B', 'C')
('A', 'C', 'B')
('B', 'A', 'C')
('B', 'C', 'A')
('C', 'A', 'B')
('C', 'B', 'A')
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)]
I am working on a backtracking solution for this problem - "Given a string s, partition s such that every substring of the partition is a palindrome."
I have written this code where I am not able to get how is the global 2D list strings is getting updated? What exactly is happening here? I tried using global keyword too with it inside palinBreak function, but it doesn't help! When should global keyword be used?
Observation: Every element of global list strings changes to local list variable arr. For instance, strings = [x, y] and arr = [z], then strings becomes [z, z, z]; whereas I want it to be [x, y, z]. Why does this happen?
EDIT: Adding expected output vs. output I am getting (take notice from line 3 onwards).
Expected output is:
ans is ['a', 'b', 'a', 'a', 'b'] []
strings is [['a', 'b', 'a', 'a', 'b']]
ans is ['a', 'b', 'aa', 'b'] [['a', 'b', 'a', 'a', 'b']]
strings is [['a', 'b', 'a', 'a', 'b'], ['a', 'b', 'aa', 'b']]
ans is ['a', 'baab'] [['a', 'b', 'a', 'a', 'b'], ['a', 'b', 'aa', 'b']]
strings is [['a', 'b', 'a', 'a', 'b'], ['a', 'b', 'aa', 'b'], ['a', 'baab']]
ans is ['aba', 'a', 'b'] [['a', 'b', 'a', 'a', 'b'], ['a', 'b', 'aa', 'b'], ['a', 'baab']]
strings is [['a', 'b', 'a', 'a', 'b'], ['a', 'b', 'aa', 'b'], ['a', 'baab'], ['aba', 'a', 'b']]
[['a', 'b', 'a', 'a', 'b'], ['a', 'b', 'aa', 'b'], ['a', 'baab'], ['aba', 'a', 'b']]
Output:
ans is ['a', 'b', 'a', 'a', 'b'] []
strings is [['a', 'b', 'a', 'a', 'b']]
ans is ['a', 'b', 'aa', 'b'] [['a', 'b', 'aa', 'b']]
strings is [['a', 'b', 'aa', 'b'], ['a', 'b', 'aa', 'b']]
ans is ['a', 'baab'] [['a', 'baab'], ['a', 'baab']]
strings is [['a', 'baab'], ['a', 'baab'], ['a', 'baab']]
ans is ['aba', 'a', 'b'] [['aba', 'a', 'b'], ['aba', 'a', 'b'], ['aba', 'a', 'b']]
strings is [['aba', 'a', 'b'], ['aba', 'a', 'b'], ['aba', 'a', 'b'], ['aba', 'a', 'b']]
[[], [], [], []]
>>>
Code:
def isPalin(s):
i = 0
j = len(s)-1
while(i<j):
if(s[i]!=s[j]):
return False
i+=1
j-=1
return True
def palinBreak(s, start, arr):
#print "Called", start, arr
#global strings
if(start==len(s)):
print "ans is", arr, strings
strings.append(arr)
print "strings is", strings
return 0
flag = -1
for i in range(1, len(s)-start+1):
curr = s[start : start+i]
#print "Testing curr and start and i", curr, start, i
if(isPalin(curr)):
arr.append(curr)
#print arr, start, i
#print "Next call from", start+i
pb = palinBreak(s, start+i, arr)
if(pb != -1):
flag = 1
arr.pop()
#print "popped l", arr
return flag
strings = []
palinBreak("abaab", 0, [])
print strings
The problem is that arr will be the same list in the inner recursive calls.
Try to replace
pb = palinBreak(s, start+i, arr)
with
pb = palinBreak(s, start+i, list(arr))
I have a Nested List like this:
l = [['A', ['A', 'B', ['A', 'B', 'C'], ['A', 'B', 'D']], ['A', 'D', ['A', 'D', 'A']], ['A', 'C', ['A', 'C', 'B'], ['A', 'C', 'A']], ['A', 'A', ['A', 'A', 'D']]]]
I want to separate it to a List of all individual lists like this:
k = [['A'], ['A', 'B'], ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'D'], ['A', 'D', 'A'], ['A', 'C'], ['A', 'C', 'B'], ['A', 'C', 'A'], ['A', 'A'], ['A', 'A', 'D']]
I tried this by creating the following function:
def un_nest(l):
k=[]
for item in l:
if type(item) is list:
un_nest(item)
else:
k+=[item]
print(k)
I got the required output, but I don't know how to convert it to list.
the output I got is:
['A', 'B', 'C']
['A', 'B', 'D']
['A', 'B']
['A', 'D', 'A']
['A', 'D']
['A', 'C', 'B']
['A', 'C', 'A']
['A', 'C']
['A', 'A', 'D']
['A', 'A']
['A']
[]
this was output in the shell, (I know this is because of print function), but i have no idea how to get the list from this. As I need to do some operation the the required list for final output.
I am using Python 3.4.1
Any hint will help. Thanks in advance
Edit:
Its more like I want to, separate all the strings and sub-list from 'l', to another list.
You could return a list as the result at the current nesting level and join together the nested results using extend.
l = [['A', ['A', 'B', ['A', 'B', 'C'], ['A', 'B', 'D']], ['A', 'D', ['A', 'D', 'A']], ['A', 'C', ['A', 'C', 'B'], ['A', 'C', 'A']], ['A', 'A', ['A', 'A', 'D']]]]
def un_nest(l):
r = []
k = []
for item in l:
if type(item) is list:
r.extend(un_nest(item))
else:
k.append(item)
if k:
r.insert(0, k)
return r
print(un_nest(l))
outputs:
[['A'], ['A', 'B'], ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'D'], ['A', 'D', 'A'], ['A', 'C'], ['A', 'C', 'B'], ['A', 'C', 'A'], ['A', 'A'], ['A', 'A', 'D']]