how to classify a list of lists by elements length? - python

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]]}

Related

how to delete the short lists from a long nested list even the items are not continuous using Python?

For example:
t=[[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
I want to delete the short lists if the items are included in a long one, even the items are not continuous. So, I expect the result to be:
[[1, 2, 3, 4, 5, 6],[6,7]]
I might figure out this by myself, but my way is not smart enough. Could anyone help me here?
Since all the elements in a list is unique, AND I like using sets
here's my code. Haven't checked it's efficiency but it looks cleaner :D
t = [[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
t = [set(l) for l in t]
t = [list(x) for x in t if not any([x.issubset(y) for y in t if x != y])]
Sort from small to large, make them sets then pop them off the list to reduce the list size for every computation.
t=[[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
t = sorted(t, key=lambda x: len(x))
t = [set(x) for x in t]
for i in range(len(t)):
a = t.pop(0)
if not any([a.issubset(x) for x in t]):
print(a)
My approach is very simple
I check the last element is already present in our longer list. If we present then we don't need to add to the longer list if it is not the case then we will add to the longerlists
sorted_lists=[[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
sorted_big_lists =[]
for sorted_list in sorted_lists:
for test_list in sorted_big_lists:
if sorted_list[-1] in test_list:
break
else:
sorted_big_lists.append(sorted_list)
print(sorted_big_lists)

How to sort a list nested inside another list?

I have lists nested inside an outer list. I want to sort the elements in inner lists without changing the position of the elements(lists in this case) in outer list. How to do it?
I am getting space separated user input which I later convert to nested lists where each inner list contain the digits of the number separated from each other. All I want is to get the inner lists in sorted form
num = list(map(str, input().split()))
n_list = []
for i in range(len(num)):
num_in_num = [int(j) for j in num[i]]
n_list.append(num_in_num)
print(n_list)
for this given input:
5654 3456 7215 7612 5463
I get the list as:
[[5, 6, 5, 4], [3, 4, 5, 6], [7, 2, 1, 5], [7, 6, 1, 2], [5, 4, 6, 3]]
I want the output to be like:
[[4, 5, 5, 6], [3, 4, 5, 6], [1, 2, 5, 7], [1, 2, 6, 7], [3, 4, 5, 6]]
How to get this output?
You can use map for this:
n_list = list(map(sorted, n_list))
or directly:
n_list = list(map(lambda n:sorted(map(int,n)), input().split())
Try a list comprehension where you map your strings to integers and then sort them using sorted
num = ['5654', '3456', '7215', '7612', '5463']
answer = [sorted(map(int, i)) for i in num]
# [[4, 5, 5, 6], [3, 4, 5, 6], [1, 2, 5, 7], [1, 2, 6, 7], [3, 4, 5, 6]]
inp = '5654 3456 7215 7612 5463' # user input
res= [] # list to store the final output
# iterating over each number which is divided into a list via inp.split()
for i in inp.split():
# keeping internal list which will keep the each digit in int format
tmp=[]
for j in i: # iterating over the number eg 5654
# converting each digit to int and adding it to temp list
tmp.append(int(j))
# sorting internal list and appending it to final result list
res.append(sorted(tmp))
print(res) # printing final list
output
[[4, 5, 5, 6], [3, 4, 5, 6], [1, 2, 5, 7], [1, 2, 6, 7], [3, 4, 5, 6]]

Python - remove duplicate of dict that contains list of lists

suppose training_data is a dict that contains a list of lists
such as {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
I want to merge each value in training_data and then flatten it once to a list so that it will become [[1,2,3,5],[1,5,6],[7,5]].
you can achieve the same result with a one-line comprehension, chaining and using a set + sort
import itertools
d = {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
result = [sorted(set(itertools.chain.from_iterable(v))) for v in d.values()]
print(result)
outputs:
[[1, 2, 3, 5], [1, 5, 6], [5, 7]]
If you only need unique elements from the list without maintaining the order of elements in initial list, then you may use set here with itertools.chain.from_iterable. You may use these with list comprehension to achieve your desired list as:
>>> from itertools import chain
>>> my_dict = {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
>>> [list(set(chain.from_iterable(v))) for v in my_dict.values()]
[[1, 2, 3, 5], [1, 5, 6], [5, 7]]
Note: since dictionaries are unordered in Python <3.6, the order of sub-lists in the resultant lists might differ.
For preserving the order of elements in the sublist while merging, take a look at: Pythonic way to merge two overlapping lists, preserving order
I found a possible solution, but could anyone tell me if there's a simpler way?
training_data = list(chain.from_iterable([transaction for _, transaction in training_data.items()]))
new_training_data = []
for transaction in training_data:
t = set()
for i in transaction:
t = t.union(i)
new_training_data.append(list(t))
You can use set with list comprehension:
training_data = {1: [[1, 2], [1, 3], [1, 2, 5]], 2: [[1], [5], [1, 6]], 3: [[7], [5]]}
resultList = [sorted(set(elem for subList in training_data[key] for elem in subList)) for key in training_data.keys()]
print(resultList)
Output:
[[1, 2, 3, 5], [1, 5, 6], [5, 7]]

How to unwrap deep list of lists in Python?

I get a nested list as input.
Simplified version is as under.
myList=[[[1,2,3],[4,5,6]],[[2,3,4],[3,4,5]],[[4,6,7],[5,7,9]]]
I wish to unpack it into a simple list of lists.
I can do like this--
simpleList=[]
for i in myList:
for j in i:
simpleList.append(j)
As desired, the simpleList is
[[1, 2, 3], [4, 5, 6], [2, 3, 4], [3, 4, 5], [4, 6, 7], [5, 7, 9]]
My question:-
What I did was, maybe, a beginner's coding approach.
Is there a more professional, efficient (and pythonic) approach to unpack this nested list?
Thanks.
EDIT:-
My method doesn't work for deeply nested lists.
e.g. [[[1,2,3],[4,5,6]],[[2,3,4],[3,4,5]],[[4,6,7],[5,7,9]],[[1,2,3],[4,5,6]],[[2,3,4],[3,4,5]],[[4,6,7],[5,7,9],[[1,2,3],[4,5,6]],[[2,3,4],[3,4,5]],[[4,6,7],[5,7,9]]]]
pl. refer to the comments to answers.
Use chain from itertools
from itertools import chain
myList=[[[1,2,3],[4,5,6]],[[2,3,4],[3,4,5]],[[4,6,7],[5,7,9]]]
print(list(chain.from_iterable(myList))) #print(list(chain(*myList)))
Output:
[[1, 2, 3], [4, 5, 6], [2, 3, 4], [3, 4, 5], [4, 6, 7], [5, 7, 9]]
You can do this using a recursive function in order to solve nested list with any depth.
def unwrap_list(mylist, result):
if any(isinstance(i, list) for i in mylist):
for value in mylist:
unwrap_list(value, result)
else:
result.append(mylist)
mylist = [[[1,2,3],[4,5,6]],[[2,3,4],[3,4,5]],[[4,6,7],[5,7,9]]]
result = []
unwrap_list(mylist, result)
print(result)
Another approach is using a generator.
def flatten(L):
for item in L:
if any(isinstance(i, list) for i in item):
yield from flatten(item)
else:
yield item
myList=[[[1,2,3],[4,5,6]],[[2,3,4],[3,4,5]],[[4,6,7],[5,7,9]]]
reduce(lambda x, y: x+y, myList)
Output:
[[1, 2, 3], [4, 5, 6], [2, 3, 4], [3, 4, 5], [4, 6, 7], [5, 7, 9]]

Append value to each sublist in a list

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]]

Categories

Resources