Related
I am trying to solve this question "Good array is the array that does not contain any equal adjacent elements.
Given an integer array A of length N, you are asked to do some operations (possibly zero) to make the
array good. One operation is to remove two equal adjacent elements and concatenate the rest of the array.
A : (1, 2, 2, 3, 4)
An after-one operation : (1, 3, 4)
" With python list, as follow:
L=[]
n=int(input("Enter a num"))
for _ in range(n):
x=int(input())
L.append(x)
print(L)
for z in range(L):
if L[z]==L[z+1]:
L.remove(z)
L.remove(z+1)
print(L)
I keep getting this error: Input In [37]
if L[z]==L[z+1]
^
SyntaxError: invalid syntax
any solutions!!`
Easiest solution is to groupby the array and just keep the groups with only one item:
>>> A = [1, 2, 2, 3, 4]
>>> import itertools
>>> A = [i for i, g in itertools.groupby(A) if len(list(g)) == 1]
>>> A
[1, 3, 4]
Edit
This is NOT correct solution of the above problem. It removes contiguous duplicates from the list. But in question, we need to keep 1 instance of duplicate element.
Please refer to #funnydman solution. Thanks #funnydman for pointing out the mistake :)
You are iterating the list and deleting items from the same :|
Not a good idea!
You can use another list to store the result.
result = []
for z in range(len(L)-1):
if L[z]!=L[z+1]:
result.append(L[z])
result.append(L[-1])
Unfortunately, Nawal's solution does not produce the correct answer, I would suggest this approach:
def get_good_array(alist):
result = []
L = alist + [None]
i = 0
while i < len(L) - 1:
if L[i] != L[i + 1]:
result.append(L[i])
i += 1
else:
i += 2
return result
assert get_good_array([1, 2, 2, 3, 4]) == [1, 3, 4]
assert get_good_array([1, 1, 2, 2, 3, 4]) == [3, 4]
assert get_good_array([0, 1, 1, 2, 2, 3, 4]) == [0, 3, 4]
assert get_good_array([1, 3, 4, 4]) == [1, 3]
assert get_good_array([1, 3, 4, 4, 5]) == [1, 3, 5]
You are missing a : at the end of the if statement, your code should look like the following
L=[]
n=int(input("Enter a num"))
for _ in range(n):
x=int(input())
L.append(x)
print(L)
for z in range(L):
if L[z]==L[z+1]:
L.remove(z)
L.remove(z+1)
print(L)
I guess using <list>.count() is quite intuitive approach. As following,
def deduplicate(l: list):
return [value for value in l if l.count(value) == 1]
assert deduplicate([2]) == [2]
assert deduplicate([2, 2]) == []
assert deduplicate([2, 2, 3]) == [3]
assert deduplicate([2, 2, 2]) == []
assert deduplicate([2, 2, 2, 3]) == [3]
I want to swap every occurrence of two elements in a list of lists. I have seen previous answers but they are different from what I'm trying to do. Also, I am looking for a clean and concise way (preferably list-comprehension) for this purpose.
Input
my_list = [[1,2], [1,3], [1,4], [3,2]]
Output
my_list = [[2,1], [2,3], [2,4], [3,1]]
I am trying to do something like this but no success:
[1 if i==2 else i, 2 if i==1 else i for i in my_list]
Here's a simple solution using list comprehension:
my_list = [[1,2], [1,3], [1,4], [3,2]]
a = 1
b = 2
my_list = [[a if i==b else b if i==a else i for i in j] for j in my_list]
print(my_list) # [[2, 1], [2, 3], [2, 4], [3, 1]]
If you want to add more elements to replace you can use a dictionary:
swap = {
1: 2,
2: 1
}
my_list = [[swap.get(i, i) for i in j] for j in my_list]
Someone else will probably answer with something better, but this would work.
def check(num):
if num == 1:
return 2
elif num == 2:
return 1
else:
return num
out = [[check(j) for j in i] for i in my_list]
If you need to swap 1's with 2's, this one-liner will work:
>>> my_list = [[1,2], [1,3], [1,4], [3,2]]
>>> print([[(lambda k: (1 if val == 2 else 2) if val in [1, 2] else val)(val) for val in sub_list] for sub_list in my_list])
[[2, 1], [2, 3], [2, 4], [3, 1]]
read the second line from right to left... in chunks!
I'm working on a project and I need to compare some values between each other and tell if they DO NOT match. I have a list of thirteen lists and each of those have more than 500 values. All thirteen lists have the same length. I would like to find an index of the item in any of those thirteen lists.
However I tried to simplify the problem by making three lists and each of those contain four items.
list1 = [1, 2, 2, 2]
list2 = [1, 3, 2, 2]
list3 = [2, 4, 2, 2]
Blist = [list1, list2, list3]
for i in range(len(Blist)): #0, 1, 2
for j in range(len(Blist)): #0, 1, 2
if i == j:
pass
else:
for k in range(len(list1)): #0, 1, 2, 3
st = Blist[i][k] != Blist[j][k]
print(st)
I could compare two lists at a time but I can't come up with the solution that would compare all items with the same index and return me a value of the index "ind" whose values don't match (when you compare list1[ind], list2[ind] and list3[ind]).
If there were only three lists I could write
for i in range(len(list1)):
if (list1[i] != list2[i] and list1[i] != list3[i] and list2[i] != list3[i])
print(i)
But I'd like to solve a problem even if it has hundreds of lists with hundreds of items.
For every index, create a set of values taking values from a single index for each nested list. As a set can't have duplicate elements, the length of the set should be equal to the total number of nested lists. Otherwise, there were duplicates, which means all the values of that index were not unique.
values = [
[1, 2, 2, 2, 5],
[1, 3, 2, 2, 7],
[2, 4, 2, 2, 1]
]
n = len(values[0]) # Number of values in each nested list
total = len(values) # Total number of nested lists
for i in range(n):
s = {v[i] for v in values}
if len(s) == total:
print(i)
Output:
1
4
If you've understood the above approach, the code can be cut down using a somewhat functional approach. Basically 2 lines of python code. (written in multiple lines for improved readability).
values = [
[1, 2, 2, 2, 5],
[1, 3, 2, 2, 7],
[2, 4, 2, 2, 1]
]
total = len(values)
# Using a list comprehension to create a list with the unique indices
unique_indices = [
idx
for idx, s in enumerate(map(set, zip(*values)))
if len(s) == total
]
print(unique_indices)
Output:
[1, 4]
if you are allowed to use numpy,
array_nd = np.array(Blist)
uniqueValues , indicesList, occurCount= numpy.unique(array_nd, return_index=True, return_counts=True)
from the above filter all of them which has occurCount as 1 and you can get its index from indicesList.
What I want this program to do is to delete all the 1's that are in the list that follow by index all the 2's.
This is the code:
a = [3, 1, 2, 1]
a.remove(a[3])
print(a)
I really put this program into the basics but the point is that I have only got the index of the 1 that follows the 2, tho when I do this the result is:
[3, 2, 1]
This means that it doesn't delete the 1 I want but just the first 1 it finds. Tho this is really a problem in a real program situation where the first 1 is an important value.
How can I fix it? Thanks
You can use list comprehension:
a = [3, 1, 2, 1]
new_a = [c for i, c in enumerate(a) if c != 1 and i+1 < len(a) and a[i+1] != 2]+[a[-1]]
Output:
[3, 2, 1]
I would use a good-ol' explicit loop for this one:
a = [3, 1, 2, 1]
b = [a[0]]
for i, item in enumerate(a[1:], 1):
if item == 1 and a[i-1] == 2:
continue
else:
b.append(item)
print(b) # -> [3, 1, 2]
Note that a does not get modified but rather a new list b is created.
If you want to remove a specific index you use del.
a = [3, 1, 2, 1]
del a[3]
print(a)
Output:
[3, 1, 2]
The del keyword might be your best bet here, for example:
a = [3, 1, 2, 1]
index = 1
while index < len(a):
if a[index - 1] == 2 and a[index] == 1:
del a[index]
else:
index += 1
print(a)
I don't know about the more pythonic way to do this, but you can keep a counter to check for the second appearance of a value you want to delete from a list.
a = [3, 1, 2, 1]
counter = 0
for i, v in enumerate(a):
if v==1:
if counter == 1:
del a[i]
else:
counter += 1
print a
#output: [3, 1, 2]
Using enumerate() and a list comprehension:
>>> a = [3, 1, 2, 1]
>>> [v for i, v in enumerate(a) if not i or not (v == 1 and a[i-1] == 2)]
[3, 1, 2]
Using list comprehension with enumerate(a) and index(2)
[j for i,j in enumerate(a) if not (i>a.index(2) and j==1)]
#[3, 1, 2]
I have a list/array(can make them arrays, doesn't matter):
array = [1,2,1,1,2,3,1,2,1,2,3,1,2,3,4,5]
I would like to create a new_array FROM array which looks like this:
new_array = [[1,2],[1],[1,2,3],[1,2],[1,2,3],[1,2,3,4,5]]
The logic I came up with was to start with a=0,b=1 and loop through array, when the value of array[a] < array[b], then a+=1,b+=1, but if the value of array[a]>=array[b], then append the value of b:
Here is what I tried:
index_1 = [] # This will be the list which will have the FIRST index
index_2 = [] # This will be the list which will have the SECOND index
a = 0
b = 1
for i in array:
if i[a] < i[b]:
a = a+1
b = b+1
elif i[a] >= i[b]:
index_2.append(b)
index_1.append(a)
So index_1 will have the first index and index_2 will have the second index and then, we can create the new_array by:
new_array = [(array[start:end]) for start,end in zip(index_1,index_2)]
Unfortunately, even though my idea is correct, the loop stops in if i[a]<i[b] because of IndexError: invalid index to scalar variable..
We can go through the array directly by the elements (more precisely by a pair of neighboring elements) simultaneously forming the result.
We initialize our result with a sublist of the 1st element of the array and then:
if the next element is greater than the previous one, we add it to the last sublist
otherwise - we add a new sublist with this element to the result.
array = [1,2,1,1,2,3,1,2,1,2,3,1,2,3,4,5]
new_array = [[array[0]]] # assume the array is not empty
for a,b in zip(array, array[1:]):
if a<b:
new_array[-1].append(b)
else:
new_array.append([b])
print(new_array)
# [[1, 2], [1], [1, 2, 3], [1, 2], [1, 2, 3], [1, 2, 3, 4, 5]]
UPD.
Alternatively, we can implement it with indices.
(based on this answer by #fortran)
First, prepare indices to split the array:
idxs_to_split = [idx for idx in range(1, len(array)) if not array[idx-1] < array[idx]]
pairs = zip([0] + idxs_to_split, idxs_to_split + [None])
Second, implement the splitting itself:
new_array = [array[i:j] for i,j in pairs]
print(new_array)
# [[1, 2], [1], [1, 2, 3], [1, 2], [1, 2, 3], [1, 2, 3, 4, 5]]
Here's a simple approach, just keep track of the previous, and check if it is smaller. If it is, append to sub. If it isnt, append sub to the new list, then create a new sub. Always append sub at the end.
>>> new_array = []
>>> array = [1,2,1,1,2,3,1,2,1,2,3,1,2,3,4,5]
>>> sub = []
>>> prev = float('-inf')
>>> for x in array:
... if prev < x:
... sub.append(x)
... else:
... new_array.append(sub)
... sub = [x]
... prev = x
...
>>> new_array.append(sub)
>>> new_array
[[1, 2], [1], [1, 2, 3], [1, 2], [1, 2, 3], [1, 2, 3, 4, 5]]
def g(l):
acc = []
for i in l:
if not acc:
acc.append(i)
else:
if acc[-1] < i:
acc.append(i)
else:
yield acc
acc = [i]
yield acc
Here's a generator version that should work for all iterables. Usage would be something like
list(g(array))
And gives the desired
[[1, 2], [1], [1, 2, 3], [1, 2], [1, 2, 3], [1, 2, 3, 4, 5]]
I simply checked for two conditions, 1. If next element == 1 and 2. If j is at last element of the list.
array = [1,2,1,1,2,3,1,2,1,2,3,1,2,3,4,5]
newList = []
j = 0
k = 0
while j < len(array)-1:
if array[j+1] ==1:
newList.append(array[k:j+1])
k = j+1
if j+2==len(array):
newList.append(array[k:j+2])
k = j + 1
j +=1
print newList