Find sublists of innermost lists in 3d list - python

I have a list l=[[[1,2,3],[4,5,6]],[[7,8,9],[9,1,2]]]
How do I get the list [[[1,2],[4,5]],[[7,8],[9,1]]] using just slicing? I tried l[:][:][:2] but it gave me the entire 3d list.

You could use a nested list comprehension, of course this ins't only using slicing but hopefully still useful:
>>> lst = [[[1,2,3],[4,5,6]],[[7,8,9],[9,1,2]]]
>>> [[subsub[:-1] for subsub in sublist] for sublist in lst]
[[[1, 2], [4, 5]], [[7, 8], [9, 1]]]

Update: just noticed your outer lists do not need slicing. In that case:
Since you are on Python2 map works well on this one:
>>> from operator import itemgetter
>>> ft = itemgetter(slice(2))
>>>
>>> map(map, (ft, ft), l)
[[[1, 2], [4, 5]], [[7, 8], [9, 1]]]
The solution below was wrongly assuming the input list was 3 x 3 x 3 and to be sliced to 2 x 2 x 2. I'll leave it here in case anybody is looking for that case.
>>> from operator import itemgetter
>>> ft = itemgetter(slice(2))
>>>
>>> map(map, (ft, ft), map(ft, l[:2]))
[[[1, 2], [4, 5]], [[7, 8], [9, 1]]]

Related

Quicker way to join multiple lists passed as args to a Python function?

So I have a function which takes a variable number of lists as an argument, then combines those lists into one single list:
def comb_lists(*lists):
sublist = []
for l in lists:
sublist.extend(l)
print(sublist)
>>> comb_lists([1, 2], [3, 4], [5, 6])
[1, 2, 3, 4, 5, 6]
And it works. But I was just wondering if there was a simpler solution? I tried a list comprehension using list unpacking, but that returned a SyntaxError:
def comb_lists(*lists):
sublist = [*l for l in lists]
>>> comb_lists([1, 2], [3, 4], [5, 6])
SyntaxError: iterable unpacking cannot be used in comprehension
Is there any neater or quicker way to do this?
EDIT: itertools looks really useful for this sort of thing. I'd be interested to know if there's any way of doing it that doesn't rely on imports though.
here is the simplest solution
result = sum(lists, [])
There's built-in function chain.form_iterable() in itertools module to do this:
>>> from itertools import chain
>>> my_list = [[1, 2], [3, 4], [5, 6]]
>>> list(chain.from_iterable(my_list))
[1, 2, 3, 4, 5, 6]
If you do not want to import any module, you can write nested list comprehension to achieve this as:
>>> my_list = [[1, 2], [3, 4], [5, 6]]
>>> [e for l in my_list for e in l]
[1, 2, 3, 4, 5, 6]

How to filter out equivalent lists of values in python?

When given a list of lists like: [[5, 2] [2, 5]]
I want to reduce this list to this: [[5, 2]] or [[2, 5]]
I've already tried the following: list(map(list, set(map(frozenset, parts_to_add))))
But the problem with this method is that it turns my lists in sets and while this works - it filters out all the equivalent lists - it also eats all of my duplicate values; When given [[3, 3]] it returns [[3]], due to the nature of sets in python. Is there another way of doing this?
Any help would be grately appreciated.
You could do :
data = [[5, 2], [2, 5], [3, 3]]
result = set(tuple(e) for e in map(sorted, data))
print([list(e) for e in result])
Output
[[2, 5], [3, 3]]
As #soon mentioned you could use a frozen Counter, for example:
from collections import Counter
data = [[5, 2], [2, 5], [3, 3]]
result = [e for e in {frozenset(Counter(e)): e for e in data}.values()]
print(result)
Output
[[2, 5], [3, 3]]
The above approach also uses a dict for removing duplicates instead of a set.
A more straightforward approach would be,
data = [[2, 5], [5, 2], [3, 6], [2, 5], [6, 3]]
result = []
for i in range(len(data)):
data[i].sort()
if data[i] not in result:
result.append(data[i])
In [49]: result
Out[49]: [[2, 5], [3, 6]]

How to do Math Functions on Lists within a List

I'm very new to python (using python3) and I'm trying to add numbers from one list to another list. The only problem is that the second list is a list of lists. For example:
[[1, 2, 3], [4, 5, 6]]
What I want is to, say, add 1 to each item in the first list and 2 to each item in the second, returning something like this:
[[2, 3, 4], [6, 7, 8]]
I tried this:
original_lst = [[1, 2, 3], [4, 5, 6]]
trasposition_lst = [1, 2]
new_lst = [x+y for x,y in zip(original_lst, transposition_ls)]
print(new_lst)
When I do this, I get an error
can only concatenate list (not "int") to list
This leads me to believe that I can't operate in this way on the lists as long as they are nested within another list. I want to do this operation without flattening the nested list. Is there a solution?
One approach using enumerate
Demo:
l = [[1, 2, 3], [4, 5, 6]]
print( [[j+i for j in v] for i,v in enumerate(l, 1)] )
Output:
[[2, 3, 4], [6, 7, 8]]
You can use enumerate:
l = [[1, 2, 3], [4, 5, 6]]
new_l = [[c+i for c in a] for i, a in enumerate(l, 1)]
Output:
[[2, 3, 4], [6, 7, 8]]
Why don't use numpy instead?
import numpy as np
mat = np.array([[1, 2, 3], [4, 5, 6]])
mul = np.array([1,2])
m = np.ones(mat.shape)
res = (m.T *mul).T + mat
You were very close with you original method. Just fell one step short.
Small addition
original_lst = [[1, 2, 3], [4, 5, 6]]
transposition_lst = [1, 2]
new_lst = [[xx + y for xx in x] for x, y in zip(original_lst, transposition_lst)]
print(new_lst)
Output
[[2, 3, 4], [6, 7, 8]]
Reasoning
If you print your original zip it is easy to see the issue. Your original zip yielded this:
In:
original_lst = [[1, 2, 3], [4, 5, 6]]
transposition_lst = [1, 2]
for x,y in zip(original_lst, transposition_lst):
print(x, y)
Output
[1, 2, 3] 1
[4, 5, 6] 2
Now it is easy to see that you are trying to add an integer to a list (hence the error). Which python doesn't understand. if they were both integers it would add them or if they were both lists it would combine them.
To fix this you need to do one extra step with your code to add the integer to each value in the list. Hence the addition of the extra list comprehension in the solution above.
A different approach than numpy that could work even for lists of different lengths is
lst = [[1, 2, 3], [4, 5, 6, 7]]
c = [1, 2]
res = [[l + c[i] for l in lst[i]] for i in range(len(c))]

Convert nested iterables to list

Is there an easy way in python (using itertools, or otherwise) to convert a nested iterable f into its corresponding list or tuple? I'd like to save f so I can iterate over it multiple times, which means that if some nested elements of f are generators, I'll be in trouble.
I'll give an example input/output.
>>> g = iter(range(2))
>>> my_input = [1, [2, 3], ((4), 5), [6, g]]
>>> magical_function(my_input)
[1, [2, 3], [[4], 5], [6, [0, 1]]]
It would be fine if the output consisted of tuples, too. The issue is that iterating over g "consumes" it, so it can't be used again.
This seems like it would be best to do by checking if each element is iterable, and calling a recursive function over it if it is iterable. Just as a quick draw-up, I would try something like:
import collections
g = iter(range(2))
my_input = [1, [2, 3], ((4), 5), [6, g]]
def unfold(iterable):
ret = []
for element in iterable:
if isinstance(element, collections.Iterable):
ret.append(unfold(element))
else:
ret.append(element)
return ret
n = unfold(my_input)
print(n)
print(n)
which returns
$ python3 so.py
[1, [2, 3], [4, 5], [6, [0, 1]]]
[1, [2, 3], [4, 5], [6, [0, 1]]]
It's not the prettiest way, and you can find ways to improve it (it puts everything in a list instead of preserving tuples), but here is the general idea I would use.

How to insert number in 2d list?

How can I insert a value, here 99, into the indices 1 producing [3,4,99] ?
x=[[1,2],[3,4],[5,6]]
x.insert(1[1],99) #this gives back 'int' object is not subscriptable
print(x)
Append the element to the list element index 1 with x[1].append(99).
>>> x=[[1,2],[3,4],[5,6]]
>>> x[1].append(99)
>>> print(x)
[[1, 2], [3, 4, 99], [5, 6]]
given the list:
x=[[1,2],[3,4],[5,6]]
if you want to insert an element in the middle of the [3,4] element:
x[1].insert(1, 3.5)
will return you
>>> x
[[1, 2], [3, 3.5, 4], [5, 6]]
if you want to add anything to the end of a list, the method for that is append:
x[1].append(5)
now you have:
>>> x
[[1, 2], [3, 3.5, 4, 5], [5, 6]]

Categories

Resources