Related
I have a list and would like to convert all duplicates values to 3 without changing the order and without importing any packages
X = [1, 2, 2, 5, 4, 8, 6]
Desired output:
X = [1, 3, 3, 5, 4, 8, 6]
This code automatically replace all duplicate items with 3
my_list = [1, 2, 2, 5, 4, 8, 6]
new = []
for item in my_list:
if my_list.count(item) > 1:
new.append(3)
else:
new.append(item)
print(new)
Among the fastest
fr = {x:0 for x in X}
for n in X:
fr[n] += 1
Y = [3 if fr[n]>1 else n for n in X]
You iterate over the list and add one to the dictionary counter for that number.
Then you create a list with list comprehension: you change the value to 3 if it is repeated more than once.
Little bit slower and little bit shorter
xi = {x:i for i, x in enumerate(X)}
dp = {x: xi[x]>i for i, x in reversed(list(enumerate(X)))}
Y = [3 if dp[x] else x for x in X]
You iterate over X and keep the lastest index of each value. Then you iterate again but in reverse order, and ask if there is another index for that value. Then with that info you create the desired output. All using list/dict comprehension. This is more of a functional approach.
Not sure why another user deleted their answer but that was a pretty simple one and uses basic list comprehension. So I am bringing the same to you. Please refer the code below for same:
X = [1, 2, 2, 5, 4, 8, 6]
print([3 if e==2 else e for e in X])
You should be able to use a for loop for this
my_list = [1, 2, 2, 5, 4, 8, 6]
new_list = []
for i in range(len(my_list)):
if my_list[i] in new_list:
new_list.append(3)
else:
new_list.append(my_list[i])
print(new_list)
Output:
[1, 3, 3, 5, 4, 8, 6]
Maybe something like this:
X = [t if t not in X[:i] + X[i+1:] else 3 for i, t in enumerate(X)]
i have a flat list that i want to transform into nested list based on the defined dimension, the length of the flat list can be arbitrary, but the dimension should satisfy the length of the list, for example
[0,1,2,3,4,5,6,7]
will produce a nested list
m = 2
n = 4
[[0,1][2,3][4,5][6,7]]
or
m = 4
n = 2
[[0,1,2,3][4,5,6,7]]
i am thinking of using list comprehension to generate the nested list, but other option can also appending element from the flat list
a = [[i] * m for i in range(n)]
You can try this:
m = 2
n = 4
nums = [i*m for i in range(1,n+1)]
[list(range(x,y)) for x, y in zip([0] + nums, nums)]
OR
nums = [i*m for i in range(n)]
[list(range(z,z+m)) for z in (nums)]
Output:
[[0, 1], [2, 3], [4, 5], [6, 7]]
For
m = 4
n = 2
Output:
[[0, 1, 2, 3], [4, 5, 6, 7]]
Here's one option using list comprehensions:
col = list(range(10))
[
col[col.index(val):col.index(val) + m]
for val in col[::len(col)//n]
]
I want my source code output to be like this:
Lists: 1 3 4 2 1 2 1 3; 4 4 2 4 3 2 4 4 3 1 3
[2, 3]
Lists : 1 1 2 3 4 5; 2 3 4 5 6
[]
Lists : ;
[]
Lists:
I want to write a function which takes two lists and returns back all the elements that occur multiple number of times in both lists but instead I end up finding common elements in these lists. My return list should be in ascending order without duplicates.
def occur_multiple(a, b):
a_set = set(a)
b_set = set(b)
# check length
if len(a_set.intersection(b_set)) > 0:
return (a_set.intersection(b_set))
else:
return ("no common elements")
while True:
original_string = input("Lists: ")
if not original_string:
exit()
first_split = original_string.split(';')
first_list, second_list = [elem.split(' ') for elem in first_split]
first_list.sort()
second_list.sort()
print(occur_multiple(first_list, second_list))
The count function for list might be helpful for your task. I have modified your code so that it go through the element in the intersection set and check if the count in both list is more than 1.
def occur_multiple(a, b):
a_set = set(a)
b_set = set(b)
# check length
ans_set = set()
c = a_set.intersection(b_set)
if len(c) > 0:
for i in c:
if a.count(i) > 1 and b.count(i) > 1:
ans_set.add(i)
return (sorted(list(ans_set)))
else:
return ("no common elements")
Also, you might like to change your list input into ints. For improvement, you might like to store the counts of each element in dictionary rather than reading the list multiple times.
Using NumPy functions np.unique and np.intersect1d:
import numpy as np
def my_fun(a, b):
val_1, count_1 = np.unique(a, return_counts=True) # Find unique elements and
val_2, count_2 = np.unique(b, return_counts=True) # number of occurrences
val_1 = val_1[count_1 > 1] # Retain elements occurring
val_2 = val_2[count_2 > 1] # more than once
result = np.intersect1d(val_1, val_2) # Set intersection
return list(result) # Convert to list
>>> a = [1, 3, 4, 2, 1, 2, 1, 3]
>>> b = [4, 4, 2, 4, 3, 2, 4, 4, 3, 1, 3]
>>> c = my_fun(a, b)
>>> print(c)
[2, 3]
>>> a = [1, 1, 2, 3, 4, 5]
>>> b = [2, 3, 4, 5, 6]
>>> c = my_fun(a, b)
>>> print(c)
[]
>>> a = [-5, 1, 2, 3, 4, 1, 0, 1, 2, 4, 4, 2, -5]
>>> b = [1, 3, 4, 5, -5, -5, -5, 1, 4]
>>> c = my_fun(a, b)
>>> print(c)
[-5, 1, 4]
Say I had a list:
lis = [4, 8, 2, 4, 6]
And I want to go through each value in the list and double it but If I come across the number 2, after I double it I should skip the next number and only double the on after. For example, in the end my list should look like this.
lis = [8, 16, 4, 4, 12]
Can this be possible with a for loop?
The algorithm boils down what number you are using to double the items in the list (1 or 2). Here is my take on this problem:
lis = [4, 8, 2, 4, 6]
def double_with_my_condition(l, doubler=2):
for i in l:
yield i * doubler
if i == 2:
doubler = 1
continue
doubler = 2
new_lis = [*double_with_my_condition(lis)]
print(new_lis)
Outputs:
[8, 16, 4, 4, 12]
I wrote out a really simple solution that should be easy to understand since it appears you are a beginner
lis = [4, 8, 2, 4, 6]
new_lis = []
i = 0
while (i < len(lis)):
new_lis.append(lis[i] * 2)
if (lis[i] == 2):
if (i+1 < len(lis)):
new_lis.append(lis[i+1])
i = i+1
i = i+1
print(new_lis)
This creates a new list, loops through the old list, appends the doubled value to the new list, skips a number if the value at the index is 2.
This will work!
Method-1:
lis = [4, 8, 2, 4, 6]
for i in range(len(lis)-1, -1, -1):
if(lis[i-1] == 2):
continue
else:
lis[i] = lis[i]*2
lis
Method-2:
lis1 = [4, 8, 2, 4, 6]
indices = [i+1 for i, x in enumerate(lis1) if x == 2] #Storing indices of next to 2
lis2 = [i*2 for i in lis1]
for i in indices:
lis2[i] = lis1[i] # replacing the previous values
print(lis2)
You can also use list comprehensions
lis = [4, 8, 2, 4, 6]
print([lis[x] if lis[x - 1] == 2 else lis[x] * 2 for x in range(len(lis))])
I am given a 1D array of numbers.
I need to go through the array adding each consecutive element to form a sum. Once this sum reaches a certain value, it forms the first element of a new array. The sum is then reset and the process repeats, thus iterating over the whole array.
For example if given:
[1, 3, 4, 5, 2, 5, 3]
and requiring the minimum sum to be 5,
the new array would be:
[8, 5, 7]
Explicity: [1 + 3 + 4, 5, 2 + 5]
I then also need to keep a record of the way the elements were combined for that particular array: I need to be to take a different array of the same length and combine the elements in the same way as above.
e.g. give the array
[1, 2, 1, 1, 3, 2, 1]
I require the output
[4, 1, 5]
Explicity: [1 + 2 + 1, 1, 3 + 2]
I have accomplished this with i loops and increment counters, but it is very ugly. The array named "record" contains the number of old elements summed to make each element of the new array i.e. [3, 1, 2]
import numpy as np
def bin(array, min_sum):
num_points = len(array)
# Create empty output.
output = list()
record = list()
i = 0
while i < num_points:
sum = 0
j = 0
while sum < min_sum:
# Break out if it reaches end of data whilst in loop.
if i+j == num_points:
break
sum += array[i+j]
j += 1
output.append(sum)
record.append(j)
i += j
# The final data point does not reach the min sum.
del output[-1]
return output
if __name__ == "__main__":
array = [1, 3, 4, 5, 2, 5, 3]
print bin(array, 5)
I would advice you to simply walk through the list. Add it to an accumulator like the_sum (do not use sum, since it is a builtin), and in case the_sum reaches a number higher than the min_sum, you add it, and reset the_sum to zero. Like:
def bin(array, min_sum):
result = []
the_sum = 0
for elem in array:
the_sum += elem
if the_sum >= min_sum:
result.append(the_sum)
the_sum = 0
return result
The lines where the accumulator is involved, are put in boldface.
I leave combining the other array the same way as an exercise, but as a hint: use an additional accumulator and zip to iterate over both arrays concurrently.
Here is a straightforward solution. which computes a list of boolean values where the value is true when accumulated element equals or exceeds the target value and calc computes an accumulation using this list.
def which(l, s):
w, a = [], 0
for e in l:
a += e
c = (a >= s)
w.append(c)
if c:
a = 0
return w
def calc(l, w):
a = 0
for (e, c) in zip(l, w):
a += e
if c:
yield a
a = 0
here is an interactive demonstration
>>> l1 = [1, 3, 4, 5, 2, 5, 3]
>>> w = which(l1, 5)
>>> w
[False, False, True, True, False, True, False]
>>> list(calc(l1, w))
[8, 5, 7]
>>> l2 = [1, 2, 1, 1, 3, 2, 1]
>>> list(calc(l2, w))
[4, 1, 5]
You can use short solutions I found out after a long struggle with flattening arrays.
For getting bounded sums use:
f = lambda a,x,j,l: 0 if j>=l else [a[i] for i in range(j,l) if sum(a[j:i])<x]
This outputs:
>>> f = lambda a,x,j,l: 0 if j>=l else [a[i] for i in range(j,l) if sum(a[j:i])< x]
>>> a= [1, 3, 4, 5, 2, 5, 3]
>>> f(a,5,0,7)
[1, 3, 4]
>>> sum(f(a,5,0,7))
8
>>> sum(f(a,5,3,7))
5
>>> sum(f(a,5,4,7))
7
>>>
To get your records use the function:
>>> y = lambda a,x,f,j,l: [] if j>=l else list(np.append(j,np.array(y(a,x,f,j+len(f(a,x,j,l)),l))))
From here, you can get both array of records and sums:
>>> listt=y(a,5,f,0,len(a))
>>> listt
[0.0, 3.0, 4.0, 6.0]
>>> [sum(f(a,5,int(listt[u]),len(a))) for u in range(0,len(listt)-1)]
[8, 5, 7]
>>>
Now, the bit of magic you can even use it as an index-conditional boundary for the second vector:
>>> b=[1, 2, 1, 1, 3, 2, 1]
>>> [sum(f(b,5,int(listt[u]),int(listt[u+1]))) for u in range(0,len(listt)-1)]
[4, 1, 5]
>>>