Remove duplicates in nested list with specified index - python

I want to remove the list which contains the maximum number( In this list 16)
Code sample
Lst = [["D",16],["B",10],["A",13],["B",16]]
required output
Lst =[["B",10],["A",13]]

You can use max to get the maximum number and then filter the original list by using list comprehension:
lst = [["D",16],["B",10],["A",13],["B",16]]
max_num = max(x[1] for x in lst)
output = [sublst for sublst in lst if sublst[1] < max_num]
print(output) # [['B', 10], ['A', 13]]

Lst = [["D",16],["B",10],["A",13],["B",16]]
max_elem = -float("inf")
for element in Lst:
if element[1] > max_elem:
max_elem = element[1]
for i in reversed(range(len(Lst))):
if Lst[i][1] == max_elem:
Lst.pop(i)
print(Lst)

Related

python list of lists contain substring

I have the list_of_lists and I need to get the string that contains 'height' in the sublists and if there is no height at all I need to get 'nvt' for the whole sublist.
I have tried the following:
list_of_lists = [['width=9','length=3'],['width=6','length=4','height=4']]
_lists = []
for list in list_of_lists:
list1 = []
for st in list:
if ("height" ) in st:
list1.append(st)
else:
list1.append('nvt')
_lists.append(list1)
OUT = _lists
the result I need to have is :
_lists = ['nvt', 'height=4']
what I'm getting is:
_lists = [['nvt','nvt'],['nvt','nvt','height=4']]
This is a good case for implementing a for/else construct as follows:
list_of_lists = [['width=9','length=3'],['width=6','length=4','height=4']]
result = []
for e in list_of_lists:
for ss in e:
if ss.startswith('height'):
result.append(ss)
break
else:
result.append('nvt')
print(result)
Output:
['nvt', 'height=4']
Note:
This could probably be done with a list comprehension but I think this is more obvious and probably has no significant difference in terms of performance
This should work, you can assign height variable to first value in the sublist where s.startswith("height") is True, and if nothing matches this filter, you can assign height to 'nvt'.
_lists = []
for sublist in list_of_lists:
height = next(filter(lambda s: s.startswith("height"), sublist), 'nvt')
_lists.append(height)
And if you wish to be crazy, you can use list comprehension to reduce the code to the:
_lists = [next(filter(lambda s: s.startswith("height"), sublist), 'nvt') for sublist in list_of_lists]
Try this (Python 3.x):
import re
list_of_lists = [['width=9','length=3'],['width=6','length=4','height=4']]
_lists = []
r = re.compile("height=")
for li in list_of_lists:
match = list(filter(r.match, li))
if len(match) > 0:
_lists.extend(match)
else:
_lists.append('nvt')
OUT = _lists
print(OUT)

Compare two lists element-wise and return the approximate value

I have two list as given below:
list1 = ['17_12_29', '17_08_04']
list2 = ['17_12_29_xyz','2017_12_29_abc', '17_08_04_mnp','17_08_04_mnp2',
'2017_08_04_def', '17_08_05_pqr']
I want to compare the two list element wise and expecting the result as given below:-
res = ['17_12_29_xyz','2017_12_29_abc', '17_08_04_mnp','17_08_04_mnp2','2017_08_04_def'].
We have different library are available to get the result, but my constraint to use python code only.
Using list comprehension and any
res = [x for x in list2 if any(y in x for y in list1)]
print(res) # Output: ['17_12_29_xyz', '2017_12_29_abc', '17_08_04_mnp', '17_08_04_mnp2', '2017_08_04_def']
This should work:
res=[]
list1 = ['17_12_29', '17_08_04']
list2 = ['17_12_29_xyz','2017_12_29_abc', '17_08_04_mnp','17_08_04_mnp2', '2017_08_04_def', '17_08_05_pqr']
for item in list2:
for j in list1:
if j in item:
res.append(item)
break
print(res)
You can check if a string exists within another string in python.
res = []
for s2 in list2:
for s1 in list1:
if s1 in s2:
res.append(s2)
You might wanna use in for comparison:
res=[]
for i in list1:
for j in list2:
if i in j:
res.append(j)

Filter a list of strings by frequency

I have a list of strings:
a = ['book','book','cards','book','foo','foo','computer']
I want to return anything in this list that's x > 2
Final output:
a = ['book','book','book']
I'm not quite sure how to approach this. But here's two methods I had in mind:
Approach One:
I've created a dictionary to count the number of times an item appears:
a = ['book','book','cards','book','foo','foo','computer']
import collections
def update_item_counts(item_counts, itemset):
for a in itemset:
item_counts[a] +=1
test = defaultdict(int)
update_item_counts(test, a)
print(test)
Out: defaultdict(<class 'int'>, {'book': 3, 'cards': 1, 'foo': 2, 'computer': 1})
I want to filter out the list with this dictionary but I'm not sure how to do that.
Approach two:
I tried to write a list comprehension but it doesn't seem to work:
res = [k for k in a if a.count > 2 in k]
A very barebone answer is that you should replace a.count by a.count(k) in your second solution.
Although, do not attempt to use list.count for this, as this will traverse the list for each item. Instead count occurences first with collections.Counter. This has the advantage of traversing the list only once.
from collections import Counter
from itertools import repeat
a = ['book','book','cards','book','foo','foo','computer']
count = Counter(a)
output = [word for item, n in count.items() if n > 2 for word in repeat(item, n)]
print(output) # ['book', 'book', 'book']
Note that the list comprehension is equivalent to the loop below.
output = []
for item, n in count.items():
if n > 2:
output.extend(repeat(item, n))
Try this:
a_list = ['book','book','cards','book','foo','foo','computer']
b_list = []
for a in a_list:
if a_list.count(a) > 2:
b_list.append(a)
print(b_list)
# ['book', 'book', 'book']
Edit: You mentioned list comprehension. You are on the right track! You can do it with list comprehension like this:
a_list = ['book','book','cards','book','foo','foo','computer']
c_list = [a for a in a_list if a_list.count(a) > 2]
Good luck!
a = ['book','book','cards','book','foo','foo','computer']
list(filter(lambda s: a.count(s) > 2, a))
Your first attempt builds a dictionary with all of the counts. You need to take this a step further to get the items that you want:
res = [k for k in test if test[k] > 2]
Now that you have built this by hand, you should check out the builtin Counter class that does all of the work for you.
If you just want to print there are better answers already, if you want to remove you can try this.
a = ['book','book','cards','book','foo','foo','computer']
countdict = {}
for word in a:
if word not in countdict:
countdict[word] = 1
else:
countdict[word] += 1
for x, y in countdict.items():
if (2 >= y):
for i in range(y):
a.remove(x)
You can try this.
def my_filter(my_list, my_freq):
'''Filter a list of strings by frequency'''
# use set() to unique my_list, then turn set back to list
unique_list = list(set(my_list))
# count frequency in unique_list
frequencies = []
for value in unique_list:
frequencies.append(my_list.count(value))
# filter frequency
return_list = []
for i, frequency in enumerate(frequencies):
if frequency > my_freq:
for _ in range(frequency):
return_list.append(unique_list[i])
return return_list
a = ['book','book','cards','book','foo','foo','computer']
my_filter(a, 2)
['book', 'book', 'book']

How to remove item in list in list with list comprehension

I have a large list like this:
mylist = [['pears','apples','40'],['grapes','trees','90','bears']]
I'm trying to remove all numbers within the lists of this list. So I made a list of numbers as strings from 1 to 100:
def integers(a, b):
return list(range(a, b+1))
numb = integers(1,100)
numbs = []
for i in range(len(numb)):
numbs.append(str(numb[i])) # strings
numbs = ['1','2',....'100']
How can I iterate through lists in mylist and remove the numbers in numbs? Can I use list comprehension in this case?
If number is always in the end in sublist
mylist = [ x[:-1] for x in mylist ]
mylist = [[item for item in sublist if item not in numbs] for sublist in mylist] should do the trick.
However, this isn't quite what you've asked. Nothing was actually removed from mylist, we've just built an entirely new list and reassigned it to mylist. Same logical result, though.
If numbers are always at the end and only once, you can remove the last item like:
my_new_list = [x[:-1] for x in mylist]
If there is more (of if they are not ordered), you have to loop thru each elements, in that case you can use:
my_new_list = [[elem for elem in x if elem not in integer_list] for x in mylist]
I would also recommend to generate the list of interger as follow :
integer_list = list(map(str, range(1, 100)))
I hope it helps :)
Instead of enumerating all the integers you want to filter out you can use the isdigit to test each string to see if it really is only numbers:
mylist = [['pears','apples','40'],['grapes','trees','90','bears']]
mylist2 = [[x for x in aList if not x.isdigit()] for aList in mylist]
print mylist2
[['pears', 'apples'], ['grapes', 'trees', 'bears']]
If you have the following list:
mylist = [['pears','apples','40'],['grapes','trees','90','bears']]
numbs = [str(i) for i in range(1, 100)]
Using list comprehension to remove element in numbs
[[l for l in ls if l not in numbs] for ls in mylist]
This is a more general way to remove digit elements in a list
[[l for l in ls if not l.isdigit()] for ls in mylist]

remove duplicate list elements

I want to remove the duplicate elements in a list only when one element is repeated many times, like this:
li = ['Human','Human','Human'] => li = ['Human']
but not when there are two or more different elements:
li = ['Human','Monkey','Human', 'Human']
You can do it easily with sets as below:
li = list(set(li))
def clean(lst):
if lst.count(lst[0]) == len(lst):
return [lst[0]]
else:
return lst
Does that do what you want?
if so, then you can do it in place as well
def clean_in_place(lst):
if lst.count(lst[0]) == len(lst):
lst[:] = [lst[0]]
lst = ['Human','Human','Human'] => lst = ['Human']
lst = ['Human','Monkey','Human', 'Human'] => lst = ['Human','Monkey','Human', 'Human']
it was do what you want?
if lst.count(lst[0])==len(lst):
lst=list(set(lst))
print lst
else:
print lst

Categories

Resources