Python - alternating lists - python

I have two lists in python:
l = [1,1,1,1,1,1]
b = ['-', 2, 2, 2, '-', 2]
In the end, I'd like to have a list like this:
result = [1, 1, 2, 1, 2, 1, 2, 1, 1, 2]
Algorithm:
If there is a '-' in b, do nothing, else append element from b after element in l at same index (Second 2 from b should go after second 1 in l). How can I do this?
for idx, i2 in enumerate(b):
if i2 != '-' and count == 1:
l.insert(prev+2,i2)
prev = prev+2
print "in if1"
print l
print prev
elif i2 != '-' and count == 0:
l.insert(idx+1,i2)
prev = idx+2
count = 1
print "in if2"
print l
print prev

l, b = [1,1,1,1,1,1], ['-', 2, 2, 2, '-', 2]
print [item for items in zip(l, b) for item in items if item != '-']
Output
[1, 1, 2, 1, 2, 1, 2, 1, 1, 2]
If the number of elements in either of the lists is not going to be equal to the other, you can use itertools.izip_longest like this
l, b = [1,1,1,1,1,1], ['-', 2, 2, 2, '-', 2, 2, 2]
from itertools import izip_longest
print [e for items in izip_longest(l,b) for e in items if e != None and e != '-']
Output
[1, 1, 2, 1, 2, 1, 2, 1, 1, 2, 2, 2]

You can used "chained" list comprehenstion (i.e. with two for loops), and a filter (x!='-'):
l1 = [1,1,1,1,1,1]
l2 = ['-', 2, 2, 2, '-', 2]
[ x for (a,b) in zip(l1,l2) for x in (a,b) if x != '-' ]
=> [1, 1, 2, 1, 2, 1, 2, 1, 1, 2]

Related

Replacing items in a list with items from another list in python

list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
Would it be possible to replace each 3 in list1 with an element from list2? If so, how would I go about doing this?
You could create an iterator for list2, and then call next() to replace the next element in list1 that is equal to 3, while using a list comprehension.
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
l2 = iter(list2)
out = [i if i!=3 else next(l2) for i in list1]
print(out)
Output:
[0, 4, 1, 1, 0, 2, 1, 0, 4, 1, 0, 2, 5]
We can use two pointers to keep track of list1 and list2. Then we replace each 3 in list1 with a value from list2 even it is not 0 until traversing to the end of any of the list.
list1 = [3, 4, 1, 1, 0, 3, 1, 0, 4, 3, 3, 2, 3]
list2 = [0, 0, 0, 0, 0]
x = 0
y = 0
while x < len(list1) and y < len(list2):
if list1[x] == 3:
list1[x] = list2[y]
y += 1
x += 1
print(list1)
Output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 0, 0, 2, 0]
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
l1_num = 3 # number to be replaced in list 1
l2_num = 0 # number to be replaced in list 2
n = min(list1.count(l1_num),list2.count(l2_num))
for i in range(n):
list1[list1.index(l1_num)] = l2_num
list2[list2.index(l2_num)] = l1_num
#list1 = [0, 4, 1, 1, 0, 0, 1, 0, 4, 3, 3, 2, 3]
#list2 = [3, 2, 1, 3, 5]
we can use for in and store our needed short list value out of the loop. like the following code will replace all 3 in list1 with zeros and all 0 in list2 with 3s in list1:
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,1,0,3,0]
#shortlistval will be used to store short list desired value
shortlistVal =1;#default val is just for declaration
for i1 in range(0, len(list1)):
for i in range(0,len(list2)):
if list1[i1] ==3 and list2[i] == 0:
shortlistVal=list2[i]
list2[i]=list1[i1]
if list1[i1]==3:
list1[i1]= shortlistVal
print(list1)
print(list2)
Output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 0, 0, 2, 0]
[3, 1, 3, 3, 3]
Use two for loops and replace each 3 for 0 s in list 2.
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
for i in range(list2.count(0)):
for x in list1:
if x == 3: list1[list1.index(x)] = 0; break
print(list1)
output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 3, 3, 2, 3]

How to create a list that represent the number of times a given item was shown?

This problem seems really stupid bu I can't get my head around it.
I have the following list:
a = [2, 1, 3, 1, 1, 2, 3, 2, 3]
I have to produce a second list which have the same size as the previous one but the values that appear should be the amount of times that a value showed up in the array until that point. For example:
b = [1, 1, 1, 2, 3, 2, 2, 3, 3]
So b[0] = 1 because it's the first time the item '2' appear on the 'a' list. b[5] = 2 and b[7] = 3 because it's the second and third time that the item '2' appear on the list 'a'.
Here a solution:
from collections import defaultdict
a = [2, 1, 3, 1, 1, 2, 3, 2, 3]
b = []
d = defaultdict(int)
for x in a:
d[x] +=1
b.append(d[x])
print(b)
Output:
[1, 1, 1, 2, 3, 2, 2, 3, 3]
I think using dictionary might help you, basically I am iterating the list and storing the current frequency of the number.
a = [2, 1, 3, 1, 1, 2, 3, 2, 3]
d = {}
z = []
for i in a:
if i not in d:
d[i] = 1
z.append(1)
else:
d[i]+=1
z.append(d[i])
print(z)
output = [1, 1, 1, 2, 3, 2, 2, 3, 3]

How sort specific items in specific order in a list

Hello everybody I am trying to do an algorithm that sort specific items in a specifig order.
Let's assume that we have a list of items :
[1, 2, 1, 3, 3, 3, 2, 2, 2, 2, 2, 1, 3, 2, 2, 1]
there is three different type of items here : 1, 2 and 3. I want to sort this list in order to have a sequence of items that follows the same types. In the sorting process we can't move the position's items, we just can remove some items and the result should be the longest.
The result of this algorithm should be :
[1, 1, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2]
I don't know why my algorithm doesn't work :
# start list
givenList = [1, 2, 1, 3, 3, 3, 2, 2, 2, 2, 2, 1, 3, 2, 2,1]
# whish list (just for an example)
whish = [1, 1, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2]
# list grouped by items ( [ [1], [2], [1], [3, 3, 3], [2, 2, 2, 2, 2] ....])
sortedList = []
# we group the elements
lastElement=0
for currentElement in givenList :
if currentElement != lastElement :
sortedList.append([currentElement])
lastElement=currentElement
else : sortedList[-1].append(currentElement)
# we print the grouped items
for index, element in enumerate(sortedList) :
print("Bloc : ", index , " contient : " , element)
# we sort the same elements by group
result=[]
for index, element in enumerate(sortedList) :
# we pass if it's the first group because he has no backward element
if(index == 0) : continue
# we pass if it's the last group because he has no afterward element
if(index == len(sortedList) - 1) : continue
# backward group
backwardList = sortedList[index - 1]
# current group
currentList = sortedList[index]
# afterward group
forwardList = sortedList[index + 1]
# if the backward groupelement type is the same as the forward
if backwardList[0] == forwardList[0] :
# and if the backwardlist contains more element that the current group
if(len(backwardList) >= len(currentList)) :
# we add the concatenation of the backwards and the forwards group
result.append(backwardList + forwardList)
elif backwardList[0] != forwardList[0] :
# else we just add the current group
result.append(currentList)
# we degroup the grouped and sorted list
resultSorted=[]
for e in result:
for i in e:
resultSorted.append(i)
#
print("#"*20)
print("Given : ", givenList)
print("Whish : ", whish)
print("Result : ", resultSorted)
print("#"*20)
You can try this implementation with itertools.groupby:
from itertools import groupby
l = [1, 2, 1, 3, 3, 3, 2, 2, 2, 2, 2, 1, 3, 2, 2, 1]
def get_max(elems, current_elems=None):
if current_elems is None:
current_elems = []
for idx, (color, count) in enumerate(elems):
if color in [c for c, _ in current_elems[:-1]]:
continue
yield current_elems + [(color, count)]
yield from get_max( elems[idx+1:], current_elems + [(color, count)] )
elems = [(v, sum(1 for _ in g)) for v, g in groupby(l)]
l, _ = max(((v, sum(c for _, c in v)) for v in get_max(elems)), key=lambda k: k[1], default=[[], None])
out = []
for v, g in groupby(l, key=lambda k: k[0]):
for _, c in g:
out.extend([v] * c)
print(out)
Prints:
[1, 1, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2]
Other test cases:
l = [1, 2, 3] # [1, 2, 3]
l = [1, 2, 3, 1, 1] # [2, 3, 1, 1]
The best solution is :
def solve(l):
def aux(i, current, exclude):
if i==len(l):
return []
val = l[i]
if val in exclude:
return aux(i+1, current, exclude)
elif val == current:
return [val] + aux(i+1, current, exclude)
else:
exclude.add(current)
s1 = [val] + aux(i+1, val, exclude)
exclude.remove(current)
s2 = aux(i+1, current, exclude)
if len(s1)>len(s2):
return s1
return s2
return aux(0, -1, set())

remove value list python

I want to multiply the values from a list and remove one value, the code is this:
list1 = [1,2,3,4]
times = 3
start = [1]
visited = [start]
list2 = [n for n in list1 * times]
list2 =
[1,2,3,4,1,2,3,4,1,2,3,4]
I want list2 to be the list1 multiply 3 times, but removing the value start, when I do this:
list2 = [(n for n in list1 * times) - start]
give an error, and
list2 = [(n for n in list1 * times) != start]
removes all the values start and I do not want that.
How can I do that the list is multiplicated by a number and then just one valueremoved? The result would be :
list2 = [2,3,4,1,2,3,4,1,2,3,4]
Thank you very much!
**One more thing, [start] in this case is 1, but it could any number present in the list.
Thank you!
You can get the l2 as follows:
l2 = (l1 * 3)[1:]
Remove first value from result list that is set in variable start
[n for i, n in enumerate(list1*times) if (i < len(list1) and n not in start) or (i >= len(list1))]
for
start = [1]
is result
[2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
for
start = [2]
is result
[1, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
etc.
Not sure if this is what you want
list1 = [1,2,3,4]
list2 = list1[1:] + list1*2
print (list2)
Use the normal multiplication operator, then the list.remove method:
>>> list1 = [1,2,3,4]
>>> times = 3
>>> start = 1
>>> list2 = list1 * times
>>> list2.remove(start)
>>> list2
[2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
This should do the trick
>>>list1 = [1, 2, 3, 4]
>>>list2 = list1 + list1 + list1
>>>list2
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
>>>list2.pop(0)
1
>>>list2
[2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4

Adjacent multiple elements removing in Python sequences

I have a sequence like [0, 1, 0, 1, 0, 1, 0] and I need a function to remove repeated adjacent sequence pairs, keeping the first one, and return [0, 1, 0]. These are some results I expect.
>>> remove_repeated_pairs([0, 1])
[0, 1]
>>> remove_repeated_pairs([0, 1, 0])
[0, 1, 0]
>>> remove_repeated_pairs([0, 1, 0, 1])
[0, 1]
>>> remove_repeated_pairs([0, 1, 0, 1, 0])
[0, 1, 0]
>>> remove_repeated_pairs([2, 0, 1, 0, 1, 0])
[2, 0, 1, 0]
>>> remove_repeated_pairs([1, 2, 0, 1, 0, 1, 0])
[1, 2, 0, 1, 0]
first edition:
I tried this code:
def remove_repeated_pairs(seq):
result = []
for i in range(0, len(seq), 2):
if len(result) >= 2:
last_seq = result[-2:]
else:
last_seq = None
pair = seq[i:i + 2]
if pair != last_seq:
result.extend(pair)
return result
But it doesn't works with this:
>>> remove_repeated_pairs([1, 3, 0, 2, 1, 2, 1, 3, 0])
[1, 3, 0, 2, 1, 2, 1, 3, 0]
The right answer should be [1, 3, 0, 2, 1, 3, 0]
I think that the issue comes from the fact that you go over the elements of your list 2 by 2 (for i in range(0, len(seq), 2).
So if a repeated pair starts on an odd place, you won't detect it - as in the last example you give.
I would try something like:
def remove_repeated_pairs(l):
i = 2;
while i < len(l)-1:
if l[i] == l[i-2] and l[i+1]==l[i-1]:
l.pop(i);
l.pop(i);
else:
i+=1;
return l;
Regards,
Here's version that works with an arbitrary iterable, not just sequences:
def remove_repeated_pairs(iterable):
it = iter(iterable)
a = next(it) # always yield the first pair
yield a
b = next(it)
yield b
c = next(it)
for d in it:
if a != c or b != d:
yield c
a, b, c = b, c, d # shift by one item
else: # repeated pair, skip it
a, b, c = c, d, next(it)
yield c
Example
>>> list(remove_repeated_pairs([1, 3, 0, 2, 1, 2, 1, 3, 0]))
[1, 3, 0, 2, 1, 3, 0]
Here is a more concise version:
def remove_repeated_pairs(seq):
pairs = zip([-1] + seq,seq)[1:]
l = [index for (index,pair) in enumerate(pairs) if (index > 1) and
(pair == pairs[index-2])]
return [seq[x] for x in range(len(seq)) if x not in l and x+1 not in l ]
print remove_repeated_pairs([1, 3, 0, 2, 1, 2, 1, 3, 0])
#OUTPUT: [1, 3, 0, 2, 1, 3, 0]
print remove_repeated_pairs([1, 2, 4, 1, 4, 1, 3])
#OUTPUT: [1, 2, 4, 1, 3]
You have to check pairs starting at odd indices as well, i.e. pairs seq[1:2] equals seq[3:4] as well as even ones, i.e. seq[0:1] equals seq[2:3]
def remove_repeated_pairs(seq):
ret = [seq[0]]
s = None
i = 1
while i < len(seq)-1:
pair = (seq[i], seq[i+1])
if pair != s:
s = (seq[i-1], seq[i])
ret.append(seq[i])
else:
i+=1
i+=1
if i == len(seq)-1:
ret.append(seq[i])
return ret
You need to move forward one by one instead of two by two
def remove_repeated_pairs(l):
if(len(l) < 4):
return l
result = l[:2]
i = 2
while i < (len(l)-1):
if l[i] == result[-2] and l[i+1] == result[-1]:
i += 2
else:
result.append(l[i])
i += 1
result += l[i:]
return result

Categories

Resources