Finding the index of the value which is the min or max in Python

前端 未结 8 641
深忆病人
深忆病人 2020-12-30 21:26

I\'ve got a structure of the form:

>>> items
[([[0, 1], [2, 20]], \'zz\', \'\'), ([[1, 3], [5, 29], [50, 500]], \'a\', \'b\')]

The

相关标签:
8条回答
  • 2020-12-30 22:22

    so this is a real quick and easy way to get that efficient version you are looking for:

    a = []
    count = 0
    for i in items:
        for x in i[0]:
            #place a list with the index next to it in list a for sorting
            a.append((x,count))
    #continually grabs the smallest list and returns the index it was in
    sort = [a.pop(a.index(min(a)))[1] for i in range(len(a))]
    

    Here is it with your items to show that it works:

    >>> items = [([[0, 1], [2, 20]], 'zz', ''), ([[1, 3], [5, 29], [50, 500]], 'a', 'b')]
    >>> a = []
    >>> count = 0
    >>> for i in items:
    ...     for x in i[0]:
    ...             a.append((x,count))
    ...     count += 1
    ... 
    >>> sort = [a.pop(a.index(min(a)))[1] for i in range(len(a))]
    >>> sort
    [0, 1, 0, 1, 1]
    
    0 讨论(0)
  • 2020-12-30 22:25

    I'm not sure what happened but I think everyone's a bit off the mark. I'll blame it on doing a bad job explaining the problem I'm trying to solve. Anyway, here's how much I've gotten:

    items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
    

    This takes me most of the way there but what's left to deal with is treating the situation where one list has been exhausted. Once that's taken care of it should be trivial to make this a generator as I can just put it in a loop and yield inside it, and also hopefully without too much more work this can be adapted into performing an efficient sort-merge over generators.

    >>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
    [0, 1]
    >>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
    [1, 3]
    >>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
    [2, 20]
    >>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in <lambda>
    IndexError: list index out of range
    

    Update:

    Assembling the proper subset of still-valid-items to min over is the ticket.

    def next_value_in_sections(sections):                 
        while 1:                                          
            idxs = []                                     
            for i, x in enumerate(sections):              
                if x[0]:                                  
                    idxs.append(i)                        
            print idxs                                    
            if not idxs:                                  
                break                                     
            j = min(idxs, key=lambda x: sections[x][0][0])
            yield (sections[j][0].pop(0), j)              
    
    items = [([[0, 1], [2, 20]], 'zz', ''),               
             ([[1, 3], [5, 29], [50, 500]], 'a', 'b')]    
    x = next_value_in_sections(items)                     
    for i in x:                                           
        print i                                           
    

    Executed:

    $ python test.py  
    [0, 1]
    ([0, 1], 0)
    [0, 1]
    ([1, 3], 1)
    [0, 1]
    ([2, 20], 0)
    [1]
    ([5, 29], 1)
    [1]
    ([50, 500], 1)
    []
    

    I'll note this still can be improved, the idxs list is being rebuilt each iteration. It does not need to be, but doing that does not improve asymptotic bound... Of course, one has to wonder if we really care about performance, whether the use of the lambda is a good idea either, though I really don't see a way around that without taking apart min, which is simply a descent into madness.

    0 讨论(0)
提交回复
热议问题