If I have two lists in Python, [0, 1] and [0, 1, 2, 3], how do I check if the first list starts with the second?
I know how to do this with strings, just use the startswith method. But apparently you can't do that for lists.
Is there a one-liner that does what I described?
Just iterate them parallelly and check that the corresponding values are equal. You can create a generator expression for the equality iterating using zip, along with all:
>>> a = [0, 1]
>>> b = [0, 1, 2, 3]
>>> all(i==j for i,j in zip(a,b))
True
This works because zip stops when the shortest iterable is exhausted.
I think this is what you meant
if the list x starts with the list y
>>> x[0:len(y)] == y
True
>>> x
[0, 1, 2, 3]
>>> y
[0, 1]
>>> a = [0, 1]
>>> b = [0, 1, 2, 3]
>>> a[:min(len(a), len(b))] == b[:min(len(a), len(b))]
True
Related
I have a long list with nested lists with each list consisting of multiple xy-coordinates.
In short, my lists looks like this
MyList = [ [ [1, 2], [1, 2] ], [ [1, 2], [1, 2] ], [ [1, 2], [1, 2] ]...]]]
I would like to extract all the "1's" to one variable, and all the "2's" to one variable.
So extract first element to a new list, and extract second element to another new list.
I have tried
for list in MyList:
for newList in list:
number1 = [item[0] for item in newList]
number2 = [item[1] for item in newList]
Which gave me the error "int object is not subscriptable".
I also tried
def Extract(MyList):
return list(list(zip(*MyList))[0])
Lastly I tried to just print the "1's" out to see if it would work
print(MyList[:][:][0])
output: [[1, 2], [1, 2]]
Try this:
flatlist = [el for lst1 in MyList for lst2 in lst1 for el in lst2]
number1, number2 = flatlist[0::2], flatlist[1::2]
First you flat the list, and then you split it into two lists with alternating elements.
I would do it like so:
>>> a = MyList
>>> x = [a[i][j][0] for i in range(len(a)) for j in range(len(a[i]))]
>>> x
[1, 1, 1, 1, 1, 1]
>>> y = [a[i][j][1] for i in range(len(a)) for j in range(len(a[i]))]
>>> y
[2, 2, 2, 2, 2, 2]
You're basically iterating over each tuple of coordinates and take the X coordinate ([0]), respectively the y coordinate ([1]).
There might be better ways, this is the quick one I came up with.
Simply you can handle this with three for loop if time complexity is not an issue:
one = []
two = []
for item in MyList:
for arr in item:
for num in arr:
if num == 1:
one.append(num)
else:
two.append(num)
# [1, 1, 1, 1, 1, 1]
# [2, 2, 2, 2, 2, 2]
Say I have an array with longitudes, lonPorts
lonPort =np.loadtxt('LongPorts.txt',delimiter=',')
for example:
lonPort=[0,1,2,3,...]
And I want to repeat each element a different amount of times. How do I do this? This is what I tried:
Repeat =[5, 3, 2, 3,...]
lonPort1=[]
for i in range (0,len(lenDates)):
lonPort1[sum(Repeat[0:i])]=np.tile(lonPort[i],Repeat[i])
So the result would be:
lonPort1=[0,0,0,0,0,1,1,1,2,2,3,3,3,...]
The error I get is:
list assignment index out of range
How do I get rid of the error and make my array?
Thank you!
You can use np.repeat():
np.repeat(a, [5,3,2,3])
Example:
In [3]: a = np.array([0,1,2,3])
In [4]: np.repeat(a, [5,3,2,3])
Out[4]: array([0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3])
Without relying on numpy, you can create a generator that will consume your items one by one, and repeat them the desired amount of time.
x = [0, 1, 2, 3]
repeat = [4, 3, 2, 1]
def repeat_items(x, repeat):
for item, r in zip(x, repeat):
while r > 0:
yield item
r -= 1
for value in repeat_items(x, repeat):
print(value, end=' ')
displays 0 0 0 0 1 1 1 2 2 3.
Providing a numpy-free solution for future readers that might want to use lists.
>>> lst = [0,1,2,3]
>>> repeat = [5, 3, 2, 3]
>>> [x for sub in ([x]*y for x,y in zip(lst, repeat)) for x in sub]
[0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3]
If lst contains mutable objects, be aware of the pitfalls of sequence multiplication for sequences holding mutable elements.
This question already has answers here:
Unable to use *= python operator in list comprehension [duplicate]
(2 answers)
Closed 4 years ago.
I want to add 5 to my specific list indices using list comprehension
Input
arr=[0,0,0,0,0]
Output
arr=[0,0,5,5,5]
I tried
[arr[i]+=5 for i in range(2,4)]
but it gives an error.
Don't use list comprehensions for side effects. The purpose of a list comp is to create a new list. To that end, I believe you can use enumerate + range here -
l, u = 2, 4
arr = [x + 5 if i in range(l, u + 1) else x for i, x in enumerate(arr)]
print(arr)
[0, 0, 5, 5, 5]
In python3, this should be very efficient because in checks on range objects are O(1) time. On python2, it would be faster to perform a boolean check (this is what an in check on range does in python3) -
arr = [x + 5 if l <= i <= u else x for i, x in enumerate(arr)]
However, keep in mind that a for loop would be the most efficient method to use here.
for i in range(l, u + 1):
arr[i] += 5
print(arr)
[0, 0, 5, 5, 5]
Because,
You only iterate over the indices you need to. Nothing more, nothing less
You make changes in place, rather than creating a new list
You can also use addition of lists by slicing them here :
arr[0:2] + [i+5 for i in arr[2:5]]
[0, 0, 5, 5, 5]
You can also try without for loop something like this:
list_1=[0,0,0,0,0]
b=list(range(2,5))
list(map(lambda x,y:list_1.__setitem__(x,list_1[x]+5),b,list_1))
print(list_1)
output:
[0, 0, 5, 5, 5]
Here's a Pythonic way to use a list comprehension to replace some indices. In this case, every index except the 2 first ones:
>>> arr = [0,0,0,0,0]
>>> arr[2:] = [i + 5 for i in arr[2:]]
>>> arr
[0, 0, 5, 5, 5]
Note that arr isn't an array, but a list. With numpy, the operation becomes easier:
>>> import numpy as np
>>> arr = np.array([0, 0, 0, 0, 0])
>>> arr
array([0, 0, 0, 0, 0])
>>> arr[2:] += 5
>>> arr
array([0, 0, 5, 5, 5])
It also works if you have a list of indices:
>>> arr = np.array([0, 0, 0, 0, 0])
>>> arr
array([0, 0, 0, 0, 0])
>>> arr[[2, 3, 4]]
array([0, 0, 0])
>>> arr[[2, 3, 4]] += 5
>>> arr
array([0, 0, 5, 5, 5])
I am looking to get the difference between two lists.
I am looking for a solution like this only I want to consider non-unique list values.
x = [1, 1, 2, 2, 3]
y = [1, 2]
# i want
z = x - y
# z = [1, 2, 3]
The solution above my code turns the two lists into sets which allows the - operator to work on them but removes non unique values from the lists. Can you think of a simple 'one liner' solution that does what im looking for?
You could use collections.Counter to find the counts of elements in each list. Then you can take the difference and reconstruct a list from the results.
>>> from collections import Counter
>>> x = [1, 1, 2, 2, 3]
>>> y = [1, 2]
>>> [k for _ in range(v) for k,v in (Counter(x) - Counter(y)).iteritems()]
[1, 2, 3]
The drawback being, the order of the result has no real correlation with the order of the input lists. The fact that the result shown above looks sorted is implementation-dependent and possibly only a coincidence.
might not be fancy, first thing that came to mind..
x=[1,1,2,2,3]
y=[1,2]
_ = [ x.remove(n) for n in y if n in x ]
x
[1,2,3]
Here's my take:
x = [1, 1, 2, 2, 3]
y = [1, 2]
z = [n for n in y if (n in x) and x.remove(n)] + x
print(z) # -> [1, 2, 3]
x = [1, 1, 1, 2]
y = [1]
z = [n for n in y if (n in x) and x.remove(n)] + x
print(z) # -> [1, 1, 2]
You just described the union of two sets, so use set:
>>> list(set(x).union(set(y)))
[1, 2, 3]
Sorry if this is a duplicate. If I have a list of lists:
j0 = [i for i in range(4)]
j1 = [j0 for j in range(4)]
>>> [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
I can get an element from each list in turn using a list comprehension:
print [j1[k][k] for k in range(0,4)]
>>> [0, 1, 2, 3]
But I want an element from each list starting from the end (so working backwards), so the desired output is:
>>> [3, 2, 1, 0] # One item from each list
I tried this but its obviously wrong because j1[0][0] = 0:
print [j1[k][-k] for k in range(0,4)]
>>>[0, 3, 2, 1]
I can use the following, but is there a nicer way using a list comprehension?
nl = []
l = 0
for i in range(-1, -5, -1):
nl.append(j1[l][i])
l += 1
print nl
This is very similar to what you have tried. You had the right idea with -k, but have to subtract it from the length (along with another -1 since python indices start at 0).
print [j1[k][len(j0) - 1 - k] for k in range(0,4)]
[3, 2, 1, 0]
you can try
print [j1[k][k] for k in range(3, -1, -1)]