How to unpack a list? - python

When extracting data from a list this way
line[0:3], line[3][:2], line[3][2:]
I receive an array and two variables after it, as should be expected:
(['a', 'b', 'c'], 'd', 'e')
I need to manipulate the list so the end result is
('a', 'b', 'c', 'd', 'e')
How? Thank you.
P.S. Yes, I know that I can write down the first element as line[0], line[1], line[2], but I think that's a pretty awkward solution.

from itertools import chain
print tuple(chain(['a', 'b', 'c'], 'd', 'e'))
Output:
('a', 'b', 'c', 'd','e')

Try this.
line = ['a', 'b', 'c', 'de']
tuple(line[0:3] + [line[3][:1]] + [line[3][1:]])
('a', 'b', 'c', 'd', 'e')
NOTE:
I think there is some funny business in your slicing logic.
If [2:] returns any characters, [:2] must return 2 characters.
Please provide your input line.

Obvious answer: Instead of your first line, do:
line[0:3] + [line[3][:2], line[3][2:]]
That works assuming that line[0:3] is a list. Otherwise, you may need to make some minor adjustments.

This function
def merge(seq):
merged = []
for s in seq:
for x in s:
merged.append(x)
return merged
source: http://www.testingreflections.com/node/view/4930

def is_iterable(i):
return hasattr(i,'__iter__')
def iterative_flatten(List):
for item in List:
if is_iterable(item):
for sub_item in iterative_flatten(item):
yield sub_item
else:
yield item
def flatten_iterable(to_flatten):
return tuple(iterative_flatten(to_flatten))
this should work for any level of nesting

Related

Enumerating all possible scenarios

I am trying to find all of the possible combinations for a set. Suppose I have 2 vehicles (A and B) and I want to use them by sending them and then return. Send and return are two distinct actions, and I want to enumerate all of the possible sequences of sending and returning this vehicle. Thus the set is [ A, A, B, B]. I use this code to enumerate:
from itertools import permutations
a = permutations(['A', 'A', 'B', 'B'])
# Print the permutations
seq = []
for i in list(a):
seq.append(i)
seq = list(set(seq)) # remove duplicates
The result is as follows:
('A', 'B', 'B', 'A')
('A', 'B', 'A', 'B')
('A', 'A', 'B', 'B')
('B', 'A', 'B', 'A')
('B', 'B', 'A', 'A')
('B', 'A', 'A', 'B')
Suppose my assumption is the two vehicles identical. Thus, it doesn't matter which one is on the first order (i.e. ABBA is the same as BAAB). Here's what I expect the result is:
('A', 'B', 'B', 'A')
('A', 'B', 'A', 'B')
('A', 'A', 'B', 'B')
I can do this easily by removing the last three elements. However, I encounter a problem when I try to do the same thing for three vehicles ( a = permutations(['A', 'A', 'B', 'B', 'C', 'C']). How to ensure that the result already considers the three identical vehicles?
One way would be to generate all the combinations, then filter for only those where the first mention of each vehicle is in alphabetical order.
In recent versions of Python, dict retains first-insertion order, so we can use it to determine the first mention; something like:
from itertools import permutations
seq = set()
for i in permutations(['A', 'A', 'B', 'B']):
first_mentions = {car: None for car in i}.keys()
if list(first_mentions) == sorted(first_mentions):
seq.add(i)
(This works in practice since Python 3.5, and officially since Python 3.7)
from itertools import permutations
a = permutations(['A', 'A', 'B', 'B'])
seq = []
for i in list(a):
if i[0]=='A':
seq.append(i)
seq = list(set(seq))
print(seq)
Try this, I think this should do

Index of a list item that occurs multiple times

I have the following code
items = ['a', 'a', 'b', 'a', 'c', 'c', 'd']
for x in items:
print(x, end='')
print(items.index(x), end='')
## out puts: a0a0b2a0c4c4d6
I understand that python finds the first item in the list to index, but is it possible for me to get an output of a0a1b2a3c4c5d6 instead?
It would be optimal for me to keep using the for loop because I will be editing the list.
edit: I made a typo with the c indexes
And in case you really feel like doing it in one line:
EDIT - using .format or format-strings makes this shorter / more legible, as noted in the comments
items = ['a', 'a', 'b', 'a', 'c', 'c', 'd']
print("".join("{}{}".format(e,i) for i,e in enumerate(items)))
For Python 3.7 you can do
items = ['a', 'a', 'b', 'a', 'c', 'c', 'd']
print("".join(f"{e}{i}" for i, e in enumerate(items)))
ORIGINAL
items = ['a', 'a', 'b', 'a', 'c', 'c', 'd']
print("".join((str(e) for item_with_index in enumerate(items) for e in item_with_index[::-1])))
Note that the reversal is needed (item_with_index[::-1]) because you want the items printed before the index but enumerate gives tuples with the index first.
I think you're looking for a0a1b2a3c4c5d6 instead.
for i, x in enumerate(items):
print("{}{}".format(x,i), end='')
Don't add or remove items from your list as you are traversing it. If you want the output specified, you can use enumerate to get the items and the indices of the list.
items = ['a', 'a', 'b', 'a', 'c', 'c', 'd']
for idx, x in enumerate(items):
print("{}{}".format(x, idx), end='')
# outputs a0a1b2a3c4c5d6

Start loop after certain element in list is reached

How do I start executing code in a for loop after a certain element in the list has been reached. I've got something that works, but is there a more pythonic or faster way of doing this?
list = ['a', 'b', 'c', 'd', 'e', 'f']
condition = 0
for i in list:
if i == 'c' or condition == 1:
condition = 1
print i
One way would to be to iterate over a generator combining dropwhile and islice:
from itertools import dropwhile, islice
data = ['a', 'b', 'c', 'd', 'e', 'f']
for after in islice(dropwhile(lambda L: L != 'c', data), 1, None):
print after
If you want including then drop the islice.
A little simplified code:
lst = ['a', 'b', 'c', 'd', 'e', 'f']
start_index = lst.index('c')
for i in lst[start_index:]:
print i

How to split line into 0,1, or 2 arrays based on line content

I am writing a program that will receive input lines in one of four structures:
a,b
(a,b,c),d
a,(b,c,d)
(a,b),(c,d)
the number of members inside each parenthesis might change. Now, I want to translate each of the above lines as following
['a','b']
[['a','b','c'],'d']
['a',['b','c','d']]
[['a','b'],['c','d']]
I can think of a way to do this by checking each character, but knowing python, I'm certain there is a way to do this easily, probably using regular expressions. Is there?
Edit: Edited the desired output.
Consider:
import re, ast
input = """
a,b
(a,b,c),d
a,(b,c,d)
(a,b),(c,d)
"""
input = re.sub(r'(\w+)', r"'\1'", input)
for line in input.strip().splitlines():
print ast.literal_eval(line)
> ('a', 'b')
> (('a', 'b', 'c'), 'd')
> ('a', ('b', 'c', 'd'))
> (('a', 'b'), ('c', 'd'))
This creates tuples, not lists, but that would be an easy fix.
Just use a regular expression to replace the parenthesis and then concatenate a [ and ] on the end of the string.
Don't use a regular expression. Use a stack instead:
def parse(inputstring):
result = []
stack = [result]
value = ''
for char in inputstring:
if char == '(':
# new context
if value:
stack[-1].append(value)
value = ''
stack[-1].append([])
stack.append(stack[-1][-1])
elif char == ')':
if value:
stack[-1].append(value)
value = ''
# pop off context
stack.pop()
elif char == ',':
if value:
stack[-1].append(value)
value = ''
else:
value += char
if value:
stack[-1].append(value)
return result
Demo:
>>> parse('a,b')
['a', 'b']
>>> parse('(a,b,c),d')
[['a', 'b', 'c'], ',d']
>>> parse('a,(b,c,d)')
['a', ['b', 'c', 'd']]
>>> parse('(a,b),(c,d)')
[['a', 'b'], ['c', 'd']]
You could do this:
import re
st = """
a,b
(a,b,c),d
a,(b,c,d)
(a,b),(c,d)
"""
def element(e):
e=e.strip()
e=re.sub(r'(\w+)',r'"\1"', e)
e=e.replace('(','[')
e=e.replace(')',']')
code=compile('temp={}'.format(e), '<string>', 'exec')
exec code
return list(temp)
print [element(x) for x in st.splitlines() if x.strip()]
# [['a', 'b'], [['a', 'b', 'c'], 'd'], ['a', ['b', 'c', 'd']], [['a', 'b'], ['c', 'd']]]

Python Remove SOME duplicates from a list while maintaining order?

I want to remove certain duplicates in my python list.
I know there are ways to remove all duplicates, but I wanted to remove only consecutive duplicates, while maintaining the list order.
For example, I have a list such as the following:
list1 = [a,a,b,b,c,c,f,f,d,d,e,e,f,f,g,g,c,c]
However, I want to remove the duplicates, and maintain order, but still keep the 2 c's and 2 f's, such as this:
wantedList = [a,b,c,f,d,e,f,g,c]
So far, I have this:
z = 0
j=0
list2=[]
for i in list1:
if i == "c":
z = z+1
if (z==1):
list2.append(i)
if (z==2):
list2.append(i)
else:
pass
elif i == "f":
j = j+1
if (j==1):
list2.append(i)
if (j==2):
list2.append(i)
else:
pass
else:
if i not in list2:
list2.append(i)
However, this method gives me something like:
wantedList = [a,b,c,c,d,e,f,f,g]
Thus, not maintaining the order.
Any ideas would be appreciated! Thanks!
Not completely sure if c and f are special cases, or if you want to compress consecutive duplicates only. If it is the latter, you can use itertools.groupby():
>>> import itertools
>>> list1
['a', 'a', 'b', 'b', 'c', 'c', 'f', 'f', 'd', 'd', 'e', 'e', 'f', 'f', 'g', 'g', 'c', 'c']
>>> [k for k, g in itertools.groupby(list1)]
['a', 'b', 'c', 'f', 'd', 'e', 'f', 'g', 'c']
To remove consecutive duplicates from a list, you can use the following generator function:
def remove_consecutive_duplicates(a):
last = None
for x in a:
if x != last:
yield x
last = x
With your data, this gives:
>>> list1 = ['a','a','b','b','c','c','f','f','d','d','e','e','f','f','g','g','c','c']
>>> list(remove_consecutive_duplicates(list1))
['a', 'b', 'c', 'f', 'd', 'e', 'f', 'g', 'c']
If you want to ignore certain items when removing duplicates...
list2 = []
for item in list1:
if item not in list2 or item in ('c','f'):
list2.append(item)
EDIT: Note that this doesn't remove consecutive items
EDIT
Never mind, I read your question wrong. I thought you were wanting to keep only certain sets of doubles.
I would recommend something like this. It allows a general form to keep certain doubles once.
list1 = ['a','a','b','b','c','c','f','f','d','d','e','e','f','f','g','g','c','c']
doubleslist = ['c', 'f']
def remove_duplicate(firstlist, doubles):
newlist = []
for x in firstlist:
if x not in newlist:
newlist.append(x)
elif x in doubles:
newlist.append(x)
doubles.remove(x)
return newlist
print remove_duplicate(list1, doubleslist)
The simple solution is to compare this element to the next or previous element
a=1
b=2
c=3
d=4
e=5
f=6
g=7
list1 = [a,a,b,b,c,c,f,f,d,d,e,e,f,f,g,g,c,c]
output_list=[list1[0]]
for ctr in range(1, len(list1)):
if list1[ctr] != list1[ctr-1]:
output_list.append(list1[ctr])
print output_list
list1 = ['a', 'a', 'b', 'b', 'c', 'c', 'f', 'f', 'd', 'd', 'e', 'e', 'f', 'f', 'g', 'g', 'c', 'c']
wantedList = []
for item in list1:
if len(wantedList) == 0:
wantedList.append(item)
elif len(wantedList) > 0:
if wantedList[-1] != item:
wantedList.append(item)
print(wantedList)
Fetch each item from the main list(list1).
If the 'temp_list' is empty add that item.
If not , check whether the last item in the temp_list is
not same as the item we fetched from 'list1'.
if items are different append into temp_list.

Categories

Resources