new_list = []
i = 0
def remove_adjacent(nums):
global i
while i < len(nums) - 1:
if nums[i] != nums[i+1]:
new_list.append(nums[i])
else:
i += 1
remove_adjacent(nums[i:])
return
i += 1
l = [1, 2, 3, 5, 4, 4, 5, 5, 6, 7, 7, 7, 8, 8, 9, 8, 8]
remove_adjacent(l)
print new_list
Question: Given a list of numbers, return a list where all adjacent == elements have been reduced to a single element, so [1, 2, 2, 3] returns [1, 2, 3]. You may create a new list or modify the passed in list.
Issue: The final list printed consists of [1, 2, 3, 5] instead of [1, 2, 3, 5, 4, 5, 6, 7, 8, 9, 8]
What you would want is a problem best solved by itertools.groupby
l
Out[35]: [1, 2, 3, 5, 4, 4, 5, 5, 6, 7, 7, 7, 8, 8, 9, 8, 8]
from itertools import groupby
[k for k, _ in groupby(l)]
Out[36]: [1, 2, 3, 5, 4, 5, 6, 7, 8, 9, 8]
What itertools.groupby does is, it groups consecutive keys together by generating a tuple of the element and the consecutive group as a list
To get a clear understanding of itertools.groupby, you can dump the resultant list of tuples generated by grouping the list of consecutive numbers
[(k, list(g)) for k, g in groupby(l)]
Out[40]:
[(1, [1]),
(2, [2]),
(3, [3]),
(5, [5]),
(4, [4, 4]),
(5, [5, 5]),
(6, [6]),
(7, [7, 7, 7]),
(8, [8, 8]),
(9, [9]),
(8, [8, 8])]
new_list = []
def remove_adjacent(nums):
i = 0
while i < len(nums) - 1:
if nums[i] != nums[i+1]:
new_list.append(nums[i])
else:
i += 1
remove_adjacent(nums[i:])
return
i += 1
l = [1, 2, 3, 5, 4, 4, 5, 5, 6, 7, 7, 7, 8, 8, 9, 8, 8]
remove_adjacent(l)
# appending the last item
new_list.append(l[len(l)-1])
print (new_list.append(nums[len(nums) - 1]))
Output
[1, 2, 3, 5, 4, 5, 6, 7, 8, 9, 8]
This is perfect for a generator. I'm not altering the original list. Instead, I'm returning a new list with no adjacent values equal to one another.
def removerator(l):
last = None
for x in l:
if x != last:
last = x
yield x
list(removerator(l))
[1, 2, 3, 5, 4, 5, 6, 7, 8, 9, 8]
Setup
l = [1, 2, 3, 5, 4, 4, 5, 5, 6, 7, 7, 7, 8, 8, 9, 8, 8]
I made a function where it get a list and iterate over its items, then it adds the items that aren't the same as the items already added to the list in the previous iteration.
l = [1, 2, 3, 5, 4, 4, 5, 5, 6, 7, 7, 7, 8, 8, 9, 8, 8] # List that we want to change
def remove_adjacent(l): # Define a new function and accept an argument: the list to check.
new = [l[0]] # Make a new list (temporal) and assing like it's first item the first item of the main list. It's the same as new = [] and new.append(l[0]).
for item in l[1:]: # We iterate across the list, but we don't iterate on the first item because we've alreaday added it to the list, if you want you can delete the slice in [1:] since it will only make the iteration a really small fraction more slowly.
if new[-1] != item: # We check if the new item is the same as the last item added to the new list, if not, we add it.
new.append(item) # We add the item to the new list.
return new # We return the list.
print(remove_adjacent(l)) # We check it.
# [1, 2, 3, 5, 4, 5, 6, 7, 8, 9, 8]
Related
I would like help with the following situation
I have two lists:
Situation 1:
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [0, 1, 2, 3, 5, 5, 6, 7, 8, 9]
I need key output: Key 4 is different
Situation 2:
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I need key output: false -> no key is different
Situation 3:
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [0, 9, 2, 3, 4, 5, 6, 7, 3, 9]
I need key output: Key 1 and Key 8 is different
How could I resolve this? My array has 260 keys
You can use a list comprehension with zip, and enumerate to get the indices. Use short-circuiting and the fact that an empty list is falsy to get False:
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [0, 1, 2, 3, 5, 5, 6, 7, 8, 9]
out = [i for i,(e1,e2) in enumerate(zip(a,b)) if e1!=e2] or False
output:
[4]
output for example #2: False
output for example #3: [1, 8]
An approach with itertools.compress. Compare the lists to check difference in values, pass the result of the comparison to compress which will pick-up only the True ones.
from itertools import compress
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [0, 1, 2, 3, 5, 5, 6, 7, 8, 9]
result = tuple(compress(a, map(int.__ne__, a, b)))
if not result:
print(False)
else:
print(result)
The current answer is really good, but for an approach which doesn't need zip/enumerate, loop like this:
lista = []
listb = []
unequal_keys = []
for idx in range(len(lista)):
if lista[idx] != listb[idx]:
unequal_keys.append(idx)
if unequal_keys == []:
print(False)
else:
print(unequal_keys)
I recommend learning new techniques and using build ins like zip and enumerate though. They are much more pythonic and faster!
I want to repeat numbers in a list but I'm not sure how to start. Here's an example of what I'm looking to do
list1=[2,4,5,1,7,8,2,9]
list_I_want=[2,2,4,4,5,5,1,1,7,7,8,8,2,2,9,9]
I was thinking probably a for loop to do this but I am not sure where to start
Here's an easy method using nested loops in a list comprehension:
>>> list1=[2,4,5,1,7,8,2,9]
>>> [i for i in list1 for _ in range(2)]
[2, 2, 4, 4, 5, 5, 1, 1, 7, 7, 8, 8, 2, 2, 9, 9]
This is equivalent to doing nested for loops and appending in the inner loop:
>>> list_i_want = []
>>> for i in list1:
... for _ in range(2):
... list_i_want.append(i)
...
>>> list_i_want
[2, 2, 4, 4, 5, 5, 1, 1, 7, 7, 8, 8, 2, 2, 9, 9]
If you want to do it in-place (i.e. without creating a separate list), you can insert each number at its position in a loop. However, the list indexes will change as you insert new items so, performing the insertions backwards will ensure that the remaining items to process are at their expected positions:
list1=[2,4,5,1,7,8,2,9]
for i in reversed(range(len(list1))):
list1.insert(i,list1[i])
print(list1)
[2, 2, 4, 4, 5, 5, 1, 1, 7, 7, 8, 8, 2, 2, 9, 9]
In a list of integer values
a = [4, 8, 2, 3, 8, 5, 8, 8, 1, 4, 8, 2, 1, 3]
I have to find the index of the last item with value 8. Is there more elegant way to do that rather than mine:
a = [4, 8, 2, 3, 8, 5, 8, 8, 1, 4, 8, 2, 1, 3]
for i in range(len(a)-1, -1, -1):
if a[i] == 8:
print(i)
break
Try This:
a = [4, 8, 2, 3, 8, 5, 8, 8, 1, 4, 8, 2, 1, 3]
index = len(a) - 1 - a[::-1].index(8)
Just reverse the array and find first index of element and then subtract it from length of array.
>>> lst = [4, 8, 2, 3, 8, 5, 8, 8, 1, 4, 8, 2, 1, 3]
>>> next(i for i in range(len(lst)-1, -1, -1) if lst[i] == 8)
10
This throws StopIteration if the list doesn't contain the search value.
Use sorted on all indexes of items with a value of 8 and take the last value, or using reverse = True take the first value
x = sorted(i for i, v in enumerate(a) if v == 8)[-1]
print(x) # => 10
If I have a list where all values are unique, the code runs fine. However, if there is a duplicate value within the list, when finding the minimum value for the next iteration, it pulls from the entire list rather than just the remainder of the list.
for n in range(0,len(lst)):
a = min(lst[n:]) #minimum value within remainder of set
i = lst.index(a) #index value for minimum value within remainder of set
temp = lst[n]
lst[n] = a
lst[i] = temp
Results look like this:
lst = [6, 8, 9, 1, 3, 4, 7, 5, 4]
[1, 8, 9, 6, 3, 4, 7, 5, 4]
[1, 3, 9, 6, 8, 4, 7, 5, 4]
[1, 3, 4, 6, 8, 9, 7, 5, 4]
[1, 3, 6, 4, 8, 9, 7, 5, 4]
[1, 3, 6, 8, 4, 9, 7, 5, 4]
[1, 3, 6, 8, 9, 4, 7, 5, 4]
[1, 3, 6, 8, 9, 7, 4, 5, 4]
[1, 3, 6, 8, 9, 7, 5, 4, 4]
[1, 3, 6, 8, 9, 7, 5, 4, 4]
I'm looking for it to return this:
[1, 3, 4, 4, 5, 6, 7, 8, 9]
When n is 4, the next minimum is 4 again, but lst.index() finds the first 4 at position 3 instead.
Start searching for the miminum from n; the .index() method takes a second argument start, from where to start searching:
i = lst.index(a, n)
Note that Python can assign to two targets in place, no need to use a temporary intermediate. range() with just one argument starts from 0:
for n in range(len(lst)):
a = min(lst[n:])
i = lst.index(a, n)
lst[n], lst[i] = a, lst[n]
Demo:
>>> lst = [6, 8, 9, 1, 3, 4, 7, 5, 4]
>>> for n in range(0,len(lst)):
... a = min(lst[n:])
... i = lst.index(a, n)
... lst[n], lst[i] = a, lst[n]
...
>>> lst
[1, 3, 4, 4, 5, 6, 7, 8, 9]
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Flatten (an irregular) list of lists in Python
Is there a way to store the results without having to write every sublist name?
the numbers in every array are just examples of what I want to do.
Thank you in advance.
_store = []
_arr4 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
_arr3 = [1, 2, 3, _arr4, 5, 6, 7, 8, 9]
_arr2 = [1, 2, 3, 4, 5, 6, _arr3, 8, 9]
_arr = [1, 2, 3, _arr2, 5, 6, 7, 8, 9]
for _value in _arr:
#If value is a list get it, go over that list and so on
if isinstance( _value, list ):
_store.append(_value)
_sub_list = _value
if isinstance( _sub_list, list ):
_store.append( _sub_list)
_sub_sub_list = _sub_list
if isinstance( _sub_sub_list, list ):
_store.append( _sub_list)
_sub_sub_sub_list = _sub_list
#and so on...
print _store
Using recursion:
a = [1,2,3]
b = [4,a,5]
c = [6,b,7]
def add_to(input, output):
for x in input:
if isinstance(x, list):
add_to(x, output)
else:
output.append(x)
result = []
add_to(c, result) # now result = [6, 4, 1, 2, 3, 5, 7]
The un-pythonicness of passing the output ref through the recursion can be eliminated by using a generator:
def flatten(input):
for x in input:
if isinstance(x, list):
for y in flatten(x):
yield y
else:
yield x
result = list(flatten(c))
Why not just serialize the list to JSON?
import json
json.dumps(arr)
You could try using recursion:
arr4 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr3 = [1, 2, 3, arr4, 5, 6, 7, 8, 9]
arr2 = [1, 2, 3, 4, 5, 6, arr3, 8, 9]
arr = [1, 2, 3, arr2, 5, 6, 7, 8, 9]
def get_store(array):
store = []
for item in array:
if isinstance(item, list):
store.extend(get_store(item))
else:
store.append(item)
return store
print get_store(arr)
...which outputs:
[1, 2, 3, 1, 2, 3, 4, 5, 6, 1, 2, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 8, 9, 5, 6, 7, 8, 9]
Basically, whenever you notice that you're taking some operation and continuously nesting or repeating it, but have difficulty turning it into a for-loop, it's a good sign that you could try recursion.