I have 2 lists:
a=[0,2,0,5]
b=[3,4,5,6]
I want to find remove all the 0 from list a and remove corresponding values(with same index) in list b.
My result should be:
a=[2,5]
b=[4,6]
until now I did:
a = [idx for idx, val in enumerate(a) if val == 0]
and get a=[1,3]
but I don't manage to get the corresponding list in b
a=[0,2,0,5]
b=[3,4,5,6]
a, b = map(list, zip(*[[i, j] for i, j in zip(a, b) if i != 0]))
print(a)
print(b)
Prints:
[2, 5]
[4, 6]
You got a list indexes correctly, to get valid elements from b list the easy way is to do
[b[idx] for idx, val in enumerate(a) if val != 0]
and to get a values
[val for val in a if val != 0]
to do it in one iteration:
x = [(val, b[idx]) for idx, val in enumerate(a) if val != 0]
or
x = [(val_a, val_b) for val_a, val_b in zip(a, b) if val_a != 0]
but it gives you list of tuples, but you can use some python magic to turn it into two lists
a, b = map(list, zip(*x))
Related
The question is odds([1, 2, 3, 4, 5, 6]) the output must be [1, 3, 5]. I know its simple in list comprehension, or a small function.
def odds(l):
r = []
for n in l:
if n % 2 == 1:
r.append(n)
return(r)```
or
def odds(l):
return [n for n in l if n % 2 == 1]
but i need the output using lambda function shown below
odds = lambda :
odds = lambda l: [x for x in l if x % 2 == 1]
Without list expression:
odds = lambda l: list(filter(lambda x:x%2==1, l))
But list expressions are the more pythonic solution always.
This stores a lambda function object in ans.
ans = lambda l: [i for i in l if i&1 == 1]
To use the function:
ans([1,2,3,4,5,6,7])
Output:
[1, 3, 5, 7]
odds = lambda _: list(filter(None, map(lambda x: x if x % 2 == 1 else None, _)))
Without using list comprehension I think there is no simpler way.
The request is to rotate a list. When K=3, you turn [1,2,3,4,5,6,7] into [5,6,7,1,2,3,4]; when K=1, you turn [1,2,3,4,5,6,7] into [7,1,2,3,4,5,6]
Why am I out of range?
PyCharm informed me like this: IndexError: list index out of range
class Solution:
def rotate(self, nums, k) -> None:
k = k%len(nums)
def rev(x, y, num):
while y > x:
num[x], num[y] = num[y], num[x]
x += 1
y -= 1
rev(0, len(nums), nums)
rev(0, k-1,nums)
rev(k, len(nums), nums)
nums = [1,2,3,4,5,6,7]
s = Solution()
s.rotate(nums,3)
You have a off by one error as the indexing starts at 0 ends at len(list)-1. You call rev like this:
rev(0, len(nums), nums)
correct would be:
rev(0, len(nums)-1, nums)
Furthermore, due to the ability to add lists and index lists with negative indices in python you can also solve the problem this way:
nums = [1,2,3,4,5,6,7]
def rotate_list(list_to_rotate, k):
return list_to_rotate[-k:] + list_to_rotate[:-k]
rotate_list(nums, 3)
# output: [5, 6, 7, 1, 2, 3, 4]
you're getting an index out of range error because you're trying to access an index in the list that doesn't exist.
Typically, your list nums has 7 elements which means you can do nums[i] if 0<=i<=6.
To fix your code you just need to replace rev(0, len(nums), nums) by rev(0, len(nums)-1, nums)
class Solution:
def rotate(self, nums, k) -> None:
k = k % len(nums)
def rev(x, y, num):
while y > x:
num[x], num[y] = num[y], num[x]
x += 1
y -= 1
rev(0, len(nums)-1, nums)
rev(0, k - 1, nums)
rev(k, len(nums)-1, nums)
nums = [1, 2, 3, 4, 5, 6, 7]
s = Solution()
s.rotate(nums, 3)
Alternatively, you can use this simpler implementation which returns another list:
class Solution:
def rotate(self, nums, k) -> list:
k = k % len(nums)
return nums[-k:] + nums[:-k]
nums = [1, 2, 3, 4, 5, 6, 7]
s = Solution()
nums = s.rotate(nums, 3)
I have two lists. I want to get matching indices. I have come up with the following to illustrate as an example:
a = [1,2,6,5,3,4]
b = [1,3,4,2,5,6]
for i in range(len(a)):
for j in range(len(b)):
if b[j] != a[i]:
next
else:
print(i, j)
Seems fairly straightforward, but a bit long. Can anyone help me make this code more efficient?
Output:
0 0
1 3
2 5
3 4
4 1
5 2
a = [1,2,6,5,3,4]
b = [1,3,4,2,5,6,1,2,3,4,5,6]
b_dict = {}
for i, n in enumerate(b):
if n not in b_dict:
b_dict[n] = []
b_dict[n].append(i)
for i in range(len(a)):
if a[i] in b_dict:
for index in b_dict[a[i]]:
print(i, index)
O(a+b) solution, since "in" in a dict is O(1)
update verion allow match duplicate number in b
You could use a list comprehension like so:
>>> a = [1,2,6,5,3,4]
>>> b = [1,3,4,2,5,6]
>>>
>>> [[i,j] for i,k in enumerate(a) for j,v in enumerate(b) if k==v]
[[0, 0], [1, 3], [2, 5], [3, 4], [4, 1], [5, 2]]
Tips
If you have a loop that uses indices and their respective values, use enumerate instead of range(len()) and indexing.
In this case you don't need to bother with the non-matching condition (if b[j] != a[i]).
>>> for i, v0 in enumerate(a):
... for j, v1 in enumerate(b):
... if v0 == v1:
... print(i, j)
...
0 0
1 3
2 5
3 4
4 1
5 2
As a list comprehension:
>>> [(i, j) for i, v0 in enumerate(a) for j, v1 in enumerate(b) if v0 == v1]
[(0, 0), (1, 3), (2, 5), (3, 4), (4, 1), (5, 2)]
(I outputted tuples cause they seem to make more sense in this context.)
Find overlap which given list, a list of intervals like [2, 4], returns whether any two intervals overlap. Boundary overlaps don't count.
Example:
`>>> check_overlap(li=[[1,5], [8,9], [3,6]])
True
>>> check_overlap(li=[[1,5], [5,6]])
False`
data= [[1, 5], [8, 9], [3, 6]]
values = [[value for value in range(elem[0], elem[1])]for elem in data]
print(values)
[[1, 2, 3, 4], [8], [3, 4, 5]]
After that i want to know how to check with each element in a list whether any two intervals overlapping.
For checking the overlap, I would sort the bigger list with first element of the sublists, and check the 2nd element of a sublist is bigger than the 1st element of the next sublist.
def overlap(li):
li.sort(key=lambda x: x[0])
for i in range(len(li)-1):
if li[i][1] > li[i+1][0]:
return True
return False
print(overlap([[1,5], [8,9], [3,6]]))
print(overlap([[1,5], [5,6]]))
True
False
I would use the itertools.combinations function as such:
from itertools import combinations
def check_overlap(li):
lists = [list(range(a, b)) for a, b in li] # Shorter way of your values = ... line
for l1, l2 in combinations(lists, 2):
if any(l in l2 for l in l1):
return True
return False
The combinations(lists, 2) call gives you all possible unique combinations of different elements.
Next, the any() function takes any iterable and returns True if any of the elements in the iterable are True (or rather 'truthy'). In this case, the l in l2 for l in l1 is a generator expression, but would work the same with square brackets around it to explicitly make it into a list first.
You can create sets and check for intersection -
data= [[1, 5], [8, 9], [3, 6]]
sets_from_data = [set(range(*l)) for l in data]
intersection_exists = bool(max([len(a.intersection(b)) for a in sets_from_data for b in sets_from_data if a != b]) > 0)
intersection_exists
# True
If you only have integers you can indeed use range to do this test:
def check_overlap(li):
ranges = [range(r[0]+1, r[1]-1) for r in li]
return any(any(e-1 in r for r in ranges) for l in li for e in l)
On the other hand, if you have floating point values you'll have to tests both bounds of the interval individually (using < and >):
def is_in_range(value, boundaries):
m, M = boundaries
return value > m+1 and value < M-1
def check_overlap(li):
return any(any(is_in_range(e, r) for r in li) for l in li for e in l)
I have three identical length lists for scatter plotting: x (float), y (float) and c (integer for colour), and would like to split up the x and y lists into subsets filtered by the colour value so that I can use a legend the delineate them in a plot
While I could achieve this with len(c) loops over the x and y lists, it is not very pythonic, and I was hoping someone could provide something a bit more elegant
I was thinking something like the following, but it's clearly not working
c_list = list(set(c))
xset = []
yset = []
for j in c_list:
xset.append([i for i in x if j in c])
yset.append([i for i in y if j in c])
Be gentle - I've only been learning Python for a week or so!
Thanks in advance
I hope this helps:
x = [1, 2, 3, 4, 5]
y = [5, 3, 1, 3, 2]
c = [1, 3, 2, 3, 1]
c_list = list(set(c))
xset = []
yset = []
for j in c_list:
xset.append([x[i] for i, v in enumerate(c) if v == j])
yset.append([y[i] for i, v in enumerate(c) if v == j])
print(xset)
print(yset)