I need to remove from a list of lists all the opposite couples of lists. For example, if my list of lists is l = [[1], [-1], [-1], [2], [2], [2], [-2]], and I need to remove the couple of opposite lists, the output should be l_out = [[-1], [2], [2]], because I remove a [1], [-1] and a [2], [-2]. How can I do this procedure recursively with a loop?
from collections import Counter
l = [[1], [-1], [-1], [2], [2], [2], [-2]]
c = Counter(v for (v, ) in l)
out = [[v] for v in c for _ in range(c.get(v, 0)-c.get(-v, 0))]
print(out)
Prints;
[[-1], [2], [2]]
So, to do this efficiently, you can keep track of the opposite in a dict along with the index it was encountered. When building up the resulting list, use None to mark spots that need to be deleted, and just do a second pass to filter out nones, making keeping track of the indices much easier:
In [1]: data = [[1], [-1], [-1], [2], [2], [2], [-2]]
In [2]: seen = {}
In [3]: result = []
...: default = 0, None
...: for i, (x,) in enumerate(data): # again, why single lists?
...: n, j = seen.get(-x, default)
...: if n == 0:
...: seen[-x] = 1, i
...: result.append([x])
...: elif n == 1:
...: seen[-x] = 0, i
...: result.append(None)
...: result[j] = None
...:
In [4]: result
Out[4]: [[1], None, None, None, None, [2], [-2]]
In [5]: [x for x in result if x is not None]
Out[5]: [[1], [2], [-2]]
So, this is still linear time, albeit, using auxiliary, linear space.
You could pop from the back as well.
l = [[1], [-1], [-1], [2], [2], [2], [-2]]
i = len(l)-1
if i%2==0:
i=i-1
while i>0:
l.pop(i)
i-=2
print(l)
Related
I want to append each element of [1,2] to [[1], [2], [3]] and as
a consequence, the final array that I want is [[1,1], [1,2], [2,1], [2,2], [3,1], [3,2]]
But my code has a mistake I couldn't recognize it yet, and the result of the python code below is [[1, 1, 2], [1, 1, 2], [2, 1, 2], [2, 1, 2], [3, 1, 2], [3, 1, 2]]
The python code:
tor=[]
arr=[1,2]
arz=[[1], [2], [3]]
each=0
while each<len(arz):
eleman=arz[each]
index=0
while index < len(arr):
k=arr[index]
eleman=arz[each]
eleman.append(k)
tor.append(eleman)
index = index+1
each=each+1
it would be eleman=arz[each].copy() as lists are mutable so every time you change an element in the original list it will get reflected in the resultant array
In this example it would be more useful to use a for loop. You can use it to loop through both lists, and append in pairs.
arr = [1, 2]
arz = [[1], [2], [3]]
tor = []
for i in arz:
for j in (arr):
tor.append([i[0], j])
print(tor)
You can use Python list comprehension to achieve this in one line:
a1 = [1, 2]
a2 = [[1], [2], [3]]
result = [[i[0], j] for i in a2 for j in a1]
print(result)
For this kind of operations don't use While loop but the for loop. It is much cleaner and simpler to use with iterables.
I have a Python list and would like to build the ranged loop list. It looks like a ring buffer. So if I have a list:
[[0], [1], [2], [3]]
I would like to get:
[[0], [1], [2], [3]]
[[1], [2], [3], [4]]
[[2], [3], [4], [0]]
[[3], [4], [0], [1]]
[[4], [0], [1], [2]]
I could do it by myself. But is there any better or smarter ways in Python 3?
The code I have tried:
N = 5
d_list = [[_] for _ in range(N)]
for i in range(N):
b1 = i
e1 = i + N - 1
b2, e2 = 0, 0
if e1 >= N:
e2 = e1 - N
print(d_list[b1:e1] + d_list[b2:e2])
what about using a collections.deque and rotate ?
import collections
N = 5
d = collections.deque(range(N))
for _ in range(N):
print(d)
d.rotate(1)
result:
deque([0, 1, 2, 3, 4])
deque([4, 0, 1, 2, 3])
deque([3, 4, 0, 1, 2])
deque([2, 3, 4, 0, 1])
deque([1, 2, 3, 4, 0])
rotate just changes the start of the list, no data is copied/moved, so it's very fast.
note:
you can convert into list if needed
my example is using integers, not lists containing one sole integer. This can be easily adapted if necessary.
This Python function rotates anything slice-able as you desire:
def rotate(l, y=1):
if len(l) == 0:
return l
y = -y % len(l) # flip rotation direction
return l[y:] + l[:y]
>>> rotate([1,2,3,4,5],2)
[4, 5, 1, 2, 3]
>>> rotate([1,2,3,4,5],-22)
[3, 4, 5, 1, 2]
>>> rotate('abcdefg',3)
'efgabcd'
>>> for i in range(N):
... print(d_list)
... d_list=rotate(d_list)
...
[[0], [1], [2], [3], [4]]
[[4], [0], [1], [2], [3]]
[[3], [4], [0], [1], [2]]
[[2], [3], [4], [0], [1]]
[[1], [2], [3], [4], [0]]
Note that in Python 3, range is not sliceable. You first would need to create a list with list(range(...))
The sign convention is the same as deque.rotate
I have a list and a function:
t = [3, [1], [2, [1], [1]]]
f = lambda x: x**2
I want the result like this:
[9, [1], [4, [1], [1]]]
I tried to use map function but it did not seem to work
I got a type error when I do this:
list(map(f, t))
if the element of t is another list, you need to map the function, not call the function. If you want this to handle arbitrary levels of nesting, f needs to be recursive.
t = [3, [1], [2, [1], [1]]]
def f(x):
if isinstance(x, list):
return map(f, x)
else:
return x**2
print(map(f, t))
You could write a recursive variant of the map function:
def recursive_map(func, iterable, *, sequence_types=(list,tuple)):
for value in iterable:
# if's a sequence, recurse
if isinstance(value, sequence_types):
cls = type(value)
values = recursive_map(func, value, sequence_types=sequence_types)
yield cls(values)
else: # if it's not a sequence, call the function on it
yield func(value)
t = [3, [1], [2, [1], [1]]]
f = lambda x: x**2
print(list(recursive_map(f, t)))
# output: [9, [1], [4, [1], [1]]]
You can use a recursion function and a list comprehension as following:
def nested_pow(arr, p):
return [pow(i, p) if isinstance(i, int) else nested_pow(i, p) for i in arr]
Demo:
In [34]: nested_pow(t, 2)
Out[34]: [9, [1], [4, [1], [1]]]
In [35]: nested_power(t, 3)
Out[35]: [27, [1], [8, [1], [1]]]
In [36]: nested_power(t, 10)
Out[36]: [59049, [1], [1024, [1], [1]]]
You need to change your function to be recursive so that it can traverse data of an arbitrary depth:
f = lambda x:x*x if not isinstance(x, list) else [f(i) for i in x]
t = [3, [1], [2, [1], [1]]]
new_result = list(map(f, t))
Output:
[9, [1], [4, [1], [1]]]
I have few lists that I want to concatenate into a new list of lists. For example, a list might look like this:
[[], []]
[[3], [1]]
[[], [5]]
[[2,5], []]
and based on this I want the output to look like:
[[3, 2, 5], [1,5]]
We cannot assume anything about the length of the lists (they will not always have two elements in the beginning, they might have more).
Here is the code I tried:
list1[l] += list2[l] #where l is an index
If we know that each top-level list shape matches all others, then we can do something like this using list comprehensions:
lists = [
[[], []],
[[3], [1]],
[[], [5]],
[[2,5], []],
]
shape=len(lists[0])
res = [[val for lst in lists for val in lst[i]] for i in range(shape) ]
print(res)
Output:
[[3, 2, 5], [1, 5]]
lst = [[[], []],[[3], [1]],[[], [5]],[[2,5], []]]
lstFinal = []
for i in range(0,len(lst[0])):
temp = []
for j in range(0,len(lst)):
temp.extend(lst[j][i])
lstFinal.append(temp)
print(lstFinal)
from functools import reduce
from operator import add
a = [[], []]
b = [[3], [1]]
c = [[], [5]]
d = [[2,5], []]
# transpose
z = zip(a, b, c, d)
# list(z) --> [([], [3], [], [2, 5]), ([], [1], [5], [])]
# flatten
def f(t):
return reduce(add, t)
m = map(f, z)
# result
for thing in m:
print(thing)
>>>
[3, 2, 5]
[1, 5]
>>>
Let's say I have a list:
l = [0,1,2,3,4]
And I want to obtain a sequence of lists in this logic:
[[1,2,3,4],[0,1,2,3],[2,3,4],[1,2,3],[0,1,2],[3,4],[2,3],[1,2],[0,1],[0],[1],[2],[3],[4]]
That's it, sublists made of l[1:] and l[:-1]
I started by this recursive function:
l = [0,1,2,3,4]
def sublist(l):
if len(l) == 1:
return l
else:
return [sublist(l[1:]),sublist(l[:-1])]
a = [sublist(l)]
print a
But it's not really what I what as it outputs:
[[[[[[4], [3]], [[3], [2]]], [[[3], [2]], [[2], [1]]]], [[[[3], [2]], [[2], [1]]], [[[2], [1]], [[1], [0]]]]]]
import itertools
[list(itertools.combinations(l, x)) for x in range(1, len(l))]
Here's a very straightforward implementation:
def sublists_n(l, n):
subs = []
for i in range(len(l)-n+1):
subs.extend([l[i:i+n]])
return subs
def sublists(l):
subs = []
for i in range(len(l)-1,0,-1):
subs.extend(sublists_n(l,i))
return subs
>>> l = [0,1,2,3,4]
>>> sublists(l)
[[0, 1, 2, 3], [1, 2, 3, 4], [0, 1, 2], [1, 2, 3], [2, 3, 4], [0, 1], [1, 2], [2, 3], [3, 4], [0], [1], [2], [3], [4]]
[l[x:] for x in range(len(l))] + [l[:x+1] for x in range(len(l))]
Loops through l twice, but you sort of have to no matter what I think (could use zip but same thing).
A simple recursion, doesn't quite order things correctly but its simple.
def sublists(l):
right = l[1:]
left = l[:-1]
result = [right, left]
if len(l) > 2:
result.extend(sublists(right))
result.extend(sublists(left))
return result
print sublists([0,1,2,3,4])