Append value to each sublist in a list - python

I have a list of list that I want to append a constant value to each sublist of the full list, for instance:
_lst = [[1, 2], [3, 4], [5, 6]]
and I want to append 7 to each of the sublist so that _lst becomes:
[[1, 2, 7], [3, 4, 7], [5, 6, 7]]
Is there a good way to complete the job (such as using zip)? Thanks!

for l in _lst:
l.append(7)

_lst = [ele + [7] for ele in _lst]

>>> tmp = [ i.append(7) for i in _lst ]
>>> print _lst
[[1, 2, 7], [3, 4, 7], [5, 6, 7]]

Related

How to get all elements at a specific depth-level in a nested list?

I am looking for a method to get all the elements nested at a user-defined list depth level e.g.:
lst = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
# example 1
level = 1 # user defined level
output = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
# example 2
level = 2
output = [[1, 2], [3, 4], [5, 6], [7, 8]]
# example 3
level = 3
output = [1, 2, 3, 4, 5, 6, 7, 8]
You can just use a recursive algorithm, for example:
output = []
def extract(lists, d):
if d == 1:
return output.extend(lists)
for sub_list in lists:
extract(sub_list, d - 1)
For level 1:
extract(lst, 1)
print(output)
>>> [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
For level 2:
extract(lst, 2)
print(output)
>>> [[1, 2], [3, 4], [5, 6], [7, 8]]
For level 3
extract(lst, 3)
print(output)
>>> [1, 2, 3, 4, 5, 6, 7, 8]
You can use chain.from_iterable to go down one level every time:
from itertools import chain
def get_at_level(lst, level):
for _ in range(level-1):
lst = chain.from_iterable(lst)
return list(lst)
Examples:
>>> lst = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
>>> get_at_level(lst, 1)
[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
>>> get_at_level(lst, 2)
[[1, 2], [3, 4], [5, 6], [7, 8]]
>>> get_at_level(lst, 3)
[1, 2, 3, 4, 5, 6, 7, 8]
Please NOTE, that the function returns only a shallow copy of the original list. So assuming you call with any level that is not the lowest - you will have the same references to sub-lists from the original. This means that modifying the returned list might* change the original! If you don't care about the original list, that's fine. If you don't want it to be changed, create a deep copy of it in the first line of the function.
* Changing the first level of the returned will not be a problem because as explained, list returns a shallow copy. BUT, doing something like get_at_level(lst, 2)[0][0] = 0 will also affect the original.
A recursive function like func as below would work.
It is basically the same as marcos' answer.
func accepts a list as its first argument and depth as the second.
from functools import reduce
lst = [[[1,2],[3,4]],[[5,6],[7,8]]]
func = lambda x, d: x if d == 1 else func(reduce(lambda a,b: a+b, x), d-1)
func(lst, 3) # output [1,2,3,4,5,6,7,8]
This isn't a very clean solution for the problem, but it works!
lst = [[[1,2],[3,4]],[[5,6],[7,8]]]
def function(lst, level):
if level == 1:
print(lst)
elif level == 2:
l2 = []
for x in lst:
for i in x:
l2.append(i)
print(l2)
elif level == 3:
l3 = []
for x in lst:
for i in x:
for a in i:
l3.append(a)
print(l3)
else:
print("Invalid depth level")
function(lst, 1) #level 1, 2 or 3
The problem here is that it isn't dynamic.
You can use a recursive generator function:
def flatten(d, l=1):
for i in d:
yield from ([i] if l == 1 else flatten(i, l-1))
lst = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
print(list(flatten(lst, 3)))
print(list(flatten(lst, 2)))
print(list(flatten(lst, 1)))
Output:
[1, 2, 3, 4, 5, 6, 7, 8]
[[1, 2], [3, 4], [5, 6], [7, 8]]
[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]

How to sort 2D list elements in python?

I need to know how to sort the list elements in python without changing their position.
a = [[5, 4, 5], [4, 5, 6], [2, 8, 2], [5, 2, 2]]
b = [[3, 2, 4], [3, 6, 7], [3, 6, 0], [7, 2, 1]]
c = [[x + y for x, y in zip(s1, s2)] for s1, s2 in zip(a, b)]
c.sort(key=lambda x: x[1])
c.reverse()
for c in c:
print(c)
I tried using the lambda but it sorts them by the first number, thus changing the order.
I need to sort array c so it would look something like this:
Input: c = [[5, 4, 5], [4, 5, 6], [2, 8, 2], [5, 2, 2]]
Output: c = [[4, 5, 5], [4, 5, 6], [2, 2, 8], [2, 2, 5]]
I hope i made myself clear enough, any help is appreciated
You can do this in your original list comprehension using sorted on the inner list comprehension.
>>> [sorted(i+j for i, j in zip(s1, s2)) for s1, s2 in zip(a, b)]
[[6, 8, 9], [7, 11, 13], [2, 5, 14], [3, 4, 12]]
for item in a:
item.sort()
You could try this:
c = [sorted(x) for x in a]

how to classify a list of lists by elements length?

I have a list of lists, looks like this :
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
I want to classify the list elements according to their length, so the result looks like this:
2ElelmentSublist=[[1,3],[4,7]]
4ElementSublist=[[3,4,7,9],[2,4,5,3]]
....
And so on.
I read a post about itertools.groupby(),
But I couldn’t figure out how to apply it in my case.
Any pythonic way to do so?
Note: no need to have the result in separate variables,I need a way to know how many types of lengths I have, and a way to reach every group separately.
Thank you in advance.
You can't make lists with dynamic names to be decided at run-time (like your 2ElementSublist or so.)
But you can design a dictionary with keys as length, and values as lists of lists.
Try this:
result = {}
for L in List:
result.setdefault(len(L), list()).append(L)
print(result)
and you will see
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
.setdefault(k, d) either gives you access to the dictionary value of key k, or initialize with a default value d. And you append each list.
Might not be the most pythonic, but you can call values similar to how you wanted.
x = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
dic = {f"{len(i)}_elelment": [] for i in x}
for i in x:
dic[f"{len(i)}_elelment"].append(i)
# {'2_elelment': [[1, 3], [4, 7]],
# '4_elelment': [[3, 4, 7, 9], [2, 4, 5, 3]],
# '3_elelment': [[5, 7, 4]]}
Since you have mentioned you need the list grouped by len and need them in seperate variable I think you will be needing a dict as your final output.
from itertools import groupby, chain
from collections import defaultdict
List=[[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
res = defaultdict(list)
for _, v in groupby(sorted(List, key=len)):
l = list(chain(*v))
res[len(l)].append(l)
# Output : defaultdict(list,
{2: [[1, 3], [4, 7]],
3: [[5, 7, 4]],
4: [[3, 4, 7, 9], [2, 4, 5, 3]]})
You can try this:
List = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
sizes = set([(len(element)) for element in List])
result = {}
for element in List:
if len(element) not in result.keys():
result[len(element)] = []
result[len(element)].append(element)
print(result)
And result is:
{2: [[1, 3], [4, 7]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]], 3: [[5, 7, 4]]}
Use groupby by len:
Ex:
from itertools import groupby
lst = [[1,3],[3,4,7,9],[4,7],[2,4,5,3],[5,7,4]]
print( [list(v) for k, v in groupby(sorted(lst, key=len), key=len)] )
#or
print( {k: list(v) for k, v in groupby(sorted(lst, key=len), key=len)} )
Output:
[[[1, 3], [4, 7]], [[5, 7, 4]], [[3, 4, 7, 9], [2, 4, 5, 3]]]
{2: [[1, 3], [4, 7]], 3: [[5, 7, 4]], 4: [[3, 4, 7, 9], [2, 4, 5, 3]]}

Delete both repeated elements from a list of lists in Python

I have the list
Input:
L = [[1, 2, 3], [2, 3, 4], [5, 6, 7], [2, 3, 4], [2, 3, 5], [1, 2, 3], [1, 2, 3]]
Output:
L= [[5, 6, 7], [ 2, 3, 5]]
I want to check if L[i]== L[j], then I will remove L[j] from the list .
Can you help me?
This is my code:
for i in range(0,len(L) - 1):
for j in range(1,len(L) - 1):
if (L[i] == L[j]):
L.remove(L[j])
print(L)
But it gives an error:
if (L[i] == L[j]):
IndexError: list index out of range
Once you remove an element of L, the shape of L changes. This is why you are getting the index out of range error: you are still iterating over the original length of L, but once you start removing elements from L it becomes shorter than that.
You can get around this by creating a new list with count:
L2 = [sublist for sublist in L if L.count(sublist) == 1]
print(L2)
>>> [[5, 6, 7], [2, 3, 5]]
Note: your current logic, even if it adapted to the changing length of L, would not return your desired output. It would still retain the first 'copy' of all duplicate elements, as Richard Rublev's answer below produces.
If this is too slow (O(n2)), here is an O(n) solution using Counter:
from collections import Counter
# Converting elements to hashable type
L = [tuple(sublist) for sublist in L]
cnt = Counter(L)
# Grabbing non-duplicated items
L2 = [k for k, v in cnt.items() if v == 1]
# Converting elements back to lists
L2 = [list(sublist) for sublist in L2]
print(L2)
>>> [[5, 6, 7], [2, 3, 5]]
Try this
testdata = [[1, 2, 3], [2, 3, 4], [5, 6, 7], [2, 3, 4], [2, 3, 5], [1, 2, 3], [1, 2, 3]]
unique = [list(x) for x in set(tuple(x) for x in testdata)]
Result
[[2, 3, 5], [2, 3, 4], [5, 6, 7], [1, 2, 3]]

Finding the differences between two nested lists

I have a nested list and another nested list which is a subset of the first list:
lst = [[1, 2], [3, 4], [1, 2], [5, 6], [8, 3], [2, 7]]
sublst = [[1, 2], [8, 3]]
How can I find the inner lists which are not in the sublist. The desired output using the above example is:
diff = [[3, 4], [5, 6], [2, 7]]
Use a list comprehension:
In [42]: lst = [[1, 2], [3, 4], [1, 2], [5, 6], [8, 3], [2, 7]]
In [43]: sublst = [[1, 2], [8, 3]]
In [44]: [x for x in lst if x not in sublst]
Out[44]: [[3, 4], [5, 6], [2, 7]]
or filter():
In [45]: filter(lambda x:x not in sublst,lst)
Out[45]: [[3, 4], [5, 6], [2, 7]]
If you convert your lists of lists to lists of tuples then you can create sets from them and use set difference operator:
lst = [[1, 2], [3, 4], [1, 2], [5, 6], [8, 3], [2, 7]]
sublst = [[1, 2], [8, 3]]
def tuples(lst): return [tuple(l) for l in lst]
print set(tuples(lst)) - set(tuples(sublst))
will print:
set([(5, 6), (2, 7), (3, 4)])
For huge lists it may be faster than evaluating [x for x in lst if x not in sublst]

Categories

Resources