In python, is it possible to check if the 2 largest values in a list are the same?
This is my code:
list=[[A, teamAScore], [B, teamBScore], [C, teamCScore], [D, teamDScore]]
list.sort()
print(max(list))
If the largest 2 values are the same, the max function will only return one of them. Is there a way to check if the two last values in the list are the same, so I can compare them in a different way? (Separate function etc etc)
A, B, C and D are Strings. teamAScore etc. are integers
I presume you want the max based on the score i.e the second element so first get the max based on the second element of each sublists scores then keep all sublists that have a score equal to the max:
from operator import itemgetter
lst = [[A, teamAScore], [B, teamBScore], [C, teamCScore], [D, teamDScore]]
# get max of list based on second element of each sublist i.e teamxScore
mx = max(lst,key=litemgetter(1)))
# use a list comp to find all sublists where teamxScore is equal to the max
maxes = [ele for ele in lst if ele[1] == mx[1]]
Demo:
l = [["foo", 2], ["bar", 1], ["foobar", 2]]
mx = max(l, key=itemgetter(1))
maxes = [ele for ele in l if ele[1] == mx[1]]
Output:
[['foo', 2], ['foobar', 2]]
Both foo and foobar had a score equal to the max so we get both sublists returned.
Related
I am trying to write something that takes a list, and gets the item(s) at an index, either one or multiple.
The example below which I found in another post here works great when I have more than one index. This example doesnt work if b = a single index.
a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [ a[i] for i in b]
How do I get this to work with both 1 and multiple index?
Example:
a = [-2,1,5,3,8,5,6]
b = 2
c = [ a[i] for i in b] doesnt work in this case
You can actually check if the type your trying to use for fetching the indices is a list (or a tuple, etc.). Here it is, wrapped into a function:
def find_values(in_list, ind):
# ind is a list of numbers
if isinstance(ind, list):
return [in_list[i] for i in ind]
else:
# ind is a single numer
return [in_list[ind]]
in_list = [-2,1,5,3,8,5,6]
list_of_indices = [1,2,5]
one_index = 3
print(find_values(in_list, list_of_indices))
print(find_values(in_list, one_index))
The function takes the input list and the indices (renamed for clarity - it's best to avoid single letter names). The indices can either be a list or a single number. If isinstance determines your input is a list, it proceeds with a list comprehension. If it's a number - it just treats it as an index. If it is anything else, the program crashes.
This post gives you more details on isinstance and recognizing other iterables, like tuples, or lists and tuples together.
a = [-2, 1, 5, 3, 8, 5, 6]
a2 = [-2]
b = [1, 2, 5]
b2 = [1]
c = [a[i] for i in b]
c2 = [a2[i-1] for i in b2]
The first item of the list is 0, the list with one item is perfectly valid.
Instead of creating a list that manually validates the value of list b in the list a, you could create a separate 3 line code to print out the overlapping intersection of list a and b by this:
a = [-2,1,5,3,8,5,6]
b = [3,4,6]
for i in range(0,len(b)):
if b[i] in a:
print(b[i])
By doing so, you would be able to print out the overlapping intersection even if there were 1 or even no value stored in list b.
I have list of lists such as :
my_list_of_list=[['A','B','C','E'],['A','B','C','E','F'],['D','G','A'],['X','Z'],['D','M'],['B','G'],['X','Z']]
as you can see, the list 1 and 2 share the most elements (4). So, I keep a list within my_list_of_list only if the 4 shared elements (A,B,C or E) are present within that list.
Here I then save within the list_shared_number[], only the lists 1,2,3 and 6 since the other does not contain (A,B,C or E).
Expected output:
print(list_shared_number)
[0,1,2,5]
Probably sub optimal because I need to iterate 3 times over lists but it's the expect result:
from itertools import combinations
from functools import reduce
common_elements = [set(i).intersection(j)
for i, j in combinations(my_list_of_list, r=2)]
common_element = reduce(lambda i, j: i if len(i) >= len(j) else j, common_elements)
list_shared_number = [idx for idx, l in enumerate(my_list_of_list)
if common_element.intersection(l)]
print(list_shared_number)
# Output
[0, 1, 2, 5]
Alternative with 2 iterations:
common_element = {}
for i, j in combinations(my_list_of_list, r=2):
c = set(i).intersection(j)
common_element = c if len(c) > len(common_element) else common_element
list_shared_number = [idx for idx, l in enumerate(my_list_of_list)
if common_element.intersection(l)]
print(list_shared_number)
# Output
[0, 1, 2, 5]
You can find shared elements by using list comprehension. Checking if index 0 and index 1:
share = [x for x in my_list_of_list[0] if x in my_list_of_list[1]]
print(share)
Assume j is each item so [j for j in x if j in share] can find shared inner elements. if the length of this array is more than 0 so it should include in the output.
So final code is like this:
share = [x for x in my_list_of_list[0] if x in my_list_of_list[1]]
my_list = [i for i, x in enumerate(my_list_of_list) if len([j for j in x if j in share]) > 0]
print(my_list)
You can use itertools.combinations and set operations.
In the first line, you find the intersection that is the longest among pairs of lists. In the second line, you iterate over my_list_of_list to identify the lists that contain elements from the set you found in the first line.
from itertools import combinations
comparison = max(map(lambda x: (len(set(x[0]).intersection(x[1])), set(x[0]).intersection(x[1])), combinations(my_list_of_list, 2)))[1]
out = [i for i, lst in enumerate(my_list_of_list) if comparison - set(lst) != comparison]
Output:
[0, 1, 2, 5]
Oh boy, so mine is a bit messy, however I did not use any imports AND I included the initial "finding" of the two lists which have the most in common with one another. This can easily be optimised but it does do exactly what you wanted.
my_list_of_list=[['A','B','C','E'],['A','B','C','E','F'],['D','G','A'],['X','Z'],['D','M'],['B','G'],['X','Z']]
my_list_of_list = list(map(set,my_list_of_list))
mostIntersects = [0, (None,)]
for i, IndSet in enumerate(my_list_of_list):
for j in range(i+1,len(my_list_of_list)):
intersects = len(IndSet.intersection(my_list_of_list[j]))
if intersects > mostIntersects[0]: mostIntersects = [intersects, (i,j)]
FinalIntersection = set(my_list_of_list[mostIntersects[1][0]]).intersection(my_list_of_list[mostIntersects[1][1]])
skipIndexes = set(mostIntersects[1])
for i,sub_list in enumerate(my_list_of_list):
[skipIndexes.add(i) for char in sub_list
if i not in skipIndexes and char in FinalIntersection]
print(*map(list,(mostIntersects, FinalIntersection, skipIndexes)), sep = '\n')
The print provides this :
[4, (0, 1)]
['E', 'C', 'B', 'A']
[0, 1, 2, 5]
This works by first converting the lists to sets using the map function (it has to be turned back into a list so i can use len and iterate properly) I then intersect each list with the others in the list of lists and count how many elements are in each. Each time i find one with a larger number, i set mostIntersections equal to the len and the set indexes. Once i go through them all, i get the lists at the two indexes (0 and 1 in this case) and intersect them to give a list of elements [A,B,C,E] (var:finalIntersection). From there, i just iterate over all lists which are not already being used and just check if any of the elements are found in finalIntersection. If one is, the index of the list is appended to skipIndexes. This results in the final list of indexes {indices? idk} that you were after. Technically the result is a set, but to convert it back you can just use list({0,1,2,5}) which will give you the value you were after.
Consider API returning four lists as output. Let's consider output as
a = [1,2,3,4]
b = [1,2,3,4]
c = [1,2,4,3]
d = [1,2,3,5]
Now, first we want to compare these lists are equal or not.
Lists are equal only if elements and there indexes matches.
For example, from above lists, a and b are equal. But a and c are not equal.
If the lists are not equal, then output is expected as: this element at this index in this list is not same as other.
For comparing and getting differences of two lists, I have written below code.
for i in range(len(a)):
if a[i] != c[i]:
print "Expected value at ",i," is ",a[i]
print "But got value ",c[i],"in second list"
Now question is how to achieve this for all four above lists?
You may use zip to iterate over each list simultaneously and compare the value at each index. In the below example, I am comparing the value of list a with remaining lists.
a = [1,2,3,4]
b = [1,2,3,4]
c = [1,2,4,3]
d = [1,2,3,5]
for i, x in enumerate(zip(a, b, c, d)):
print('--------- Index: {}'.format(i))
base = x[0]
for j, y in enumerate(x[1:], 2):
if base!=y:
print('{} not equal to {} : --> List {}'.format(base, y, j))
which prints:
--------- Index: 0
--------- Index: 1
--------- Index: 2
3 not equal to 4 : --> List 3
--------- Index: 3
4 not equal to 3 : --> List 3
4 not equal to 5 : --> List 4
From the comment:
How to find in which list we have different value?
import collections as ct
counter = ct.Counter(map(tuple, [a,b,c,d])) # make hashable keys w/tuples
base = counter.most_common(1)[0][0] # find most frequent sequence
[list(seq) for seq in counter if seq != base] # filter uncommon sequences
Output (the non-matching lists):
[[1, 2, 4, 3], [1, 2, 3, 5]]
We collect all similar sequences as keys in a collections.Counter. If all sequences match, there should only be one entry in the Counter dictionary. Otherwise, filter the remaining sequences.
Set up a list mylist = [a, b, c,d] Then loop through checking which ones are equal and which ones are not equal.
for i in range(len(mylist)-1)
for j in range(i+1, len(mylist))
# Check mylist[i] agaist mylist[j] and report results
For example, this will test a against b, c, and d
b against c and d
c against d
How do I check in Python, if an item of a list is repetead in another list?
I suppose that I should use a FOR loop, to go and check item by item, but I´m stuck in something like this (which I know it´s not correct):
def check(a, b):
for item in b:
for item1 in a:
if b[item] in a[item1]:
b.remove(b[item1])
I want to remove repeated elements in the second list in comparision with the first list.
Edit: I do assume that list a has items that are repeated in list b. Those items can be of any type.
Desired output:
a=[a,b,c]
b=[c,d,e]
I want to append both lists and print: a b c d e
Assuming that a and b do not contain duplicate items that need to be preserved and the items are all hashable, you can use Python has a built in set:
c = list(set(b) - set(a))
# c is now a list of everything in b that is not in a
This would work for:
a, b = range(7), range(5, 11)
but it would not work for:
a = [1, 2, 1, 1, 3, 4, 2]
b = [1, 3, 4]
# After the set operations c would be [2]
# rather than the possibly desired [2, 2]
In the case when duplicates are desired you can do the following:
set_b = set(b)
c = [x for x in a if x not in b]
Using a set for b will make the lookups O(1) rather than O(N) (which will not matter for small lists).
You can use Python's set operations without the need for loops:
>>> a = [1,2]
>>> b = [2]
>>> set(a) - set(b)
set([1])
>>>
Use the set command and list to get the list back.
d = list(set(a + b))
You can use list.sort() if you want to sort the list as well.
I'm looking for a way to make a list containing list (a below) into a single list (b below) with 2 conditions:
The order of the new list (b) is based on the number of times the value has occurred in some of the lists in a.
A value can only appear once
Basically turn a into b:
a = [[1,2,3,4], [2,3,4], [4,5,6]]
# value 4 occurs 3 times in list a and gets first position
# value 2 occurs 2 times in list a and get second position and so on...
b = [4,2,3,1,5,6]
I figure one could do this with set and some list magic. But can't get my head around it when a can contain any number of list. The a list is created based on user input (I guess that it can contain between 1 - 20 list with up 200-300 items in each list).
My trying something along the line with [set(l) for l in a] but don't know how to perform set(l) & set(l).... to get all matched items.
Is possible without have a for loop iterating sublist count * items in sublist times?
I think this is probably the closest you're going to get:
from collections import defaultdict
d = defaultdict(int)
for sub in outer:
for val in sub:
d[val] += 1
print sorted(d.keys(), key=lambda k: d[k], reverse = True)
# Output: [4, 2, 3, 1, 5, 6]
There is an off chance that the order of elements that appear an identical number of times may be indeterminate - the output of d.keys() is not ordered.
import itertools
all_items = set(itertools.chain(*a))
b = sorted(all_items, key = lambda y: -sum(x.count(y) for x in a))
Try this -
a = [[1,2,3,4], [2,3,4], [4,5,6]]
s = set()
for l in a:
s.update(l)
print s
#set([1, 2, 3, 4, 5, 6])
b = list(s)
This will add each list to the set, which will give you a unique set of all elements in all the lists. If that is what you are after.
Edit. To preserve the order of elements in the original list, you can't use sets.
a = [[1,2,3,4], [2,3,4], [4,5,6]]
b = []
for l in a:
for i in l:
if not i in b:
b.append(i)
print b
#[1,2,3,4,5,6] - The same order as the set in this case, since thats the order they appear in the list
import itertools
from collections import defaultdict
def list_by_count(lists):
data_stream = itertools.chain.from_iterable(lists)
counts = defaultdict(int)
for item in data_stream:
counts[item] += 1
return [item for (item, count) in
sorted(counts.items(), key=lambda x: (-x[1], x[0]))]
Having the x[0] in the sort key ensures that items with the same count are in some kind of sequence as well.