简体   繁体   中英

Python - query over list of tuples

I have a list of tuples that contain a float, and two custom objects:

ExampleList = [(10.5, Obj1, Obj2), (11.5, Obj1, Obj2), (14., Obj1, Obj2)]

I then have a line of code that appends tuples to that:

newTuple = (15,Obj1, Obj2)    
ExampleList.append(newTuple)

I am trying to figure out a clean way to add the following kind of line:

If newTuple[0] (the float number) is > than any of the 2nd largest tuple float numbers, append it. Otherwise no. Any idea how to do that element-wise boolean on a tuple list?

EDIT - sorry, I meant to add the 2nd largest part.

Thanks- KC

Here's the cleanest way to do it (that I am aware of):

secondLargest = sorted(ExampleList)[-2][0]
if (newTuple[0] > secondLargest):
    ExampleList.append(newTuple)

Although If you're looking for efficiency, look at @Jean-François Fabre 's answer

max is ruled out here, since we need the 2nd best value. sort would work but it allocates the full sorted list in return, only to discard most of the values.

A nice way of getting the 2nd largest float is to use heapq.nlargest in a generator comprehension (better check that input list has at least 2 elements in the general case, though)

import heapq

Obj1 = object()
Obj2 = object()

sampleList = [(10.5, Obj1, Obj2), (11.5, Obj1, Obj2), (14., Obj1, Obj2)]

second_largest = heapq.nlargest(2,(x[0] for x in sampleList))[-1]  # [14.0, 11.5]

newTuple = (15,Obj1, Obj2)

if newTuple[0]>second_largest:
    sampleList.append(newTuple)

Since your list is already sorted, I would look at the bisect module to find the sorted insertion point. Then just calculate if that insertion meets the criteria.

Example:

import bisect

Obj1='o1'
Obj2='o2'
sample=[(10.5, Obj1, Obj2), (11.5, Obj1, Obj2), (14., Obj1, Obj2)] # needs to be sorted

newTuple = (13,Obj1, Obj2)

def my_insert(li, t):
    ip=bisect.bisect_left(li, newTuple)
    if len(li)-ip<2:
        li.insert(ip, t)
    else:
        print t, 'not inserted' 

Testing:

>>> my_insert(sample, newTuple); print sample
[(10.5, 'o1', 'o2'), (11.5, 'o1', 'o2'), (13, 'o1', 'o2'), (14.0, 'o1', 'o2')]
>>> my_insert(sample, newTuple); print sample
(13, 'o1', 'o2') not inserted
[(10.5, 'o1', 'o2'), (11.5, 'o1', 'o2'), (13, 'o1', 'o2'), (14.0, 'o1', 'o2')]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM