简体   繁体   English

通过检查 max 和 mins 从列表中选择子列表

[英]Select sublist from list by checking max and mins

Background:背景:

I have a list of lists, where each inner list is of the same length:我有一个列表列表,其中每个内部列表的长度相同:

list_of_lists = [[1.0, 3.0, 5.0], [3.0, 5.0, 0.0], [2.0, 1.0, 4.0]]

I would like to find the inner list that meets the following criteria:我想找到满足以下条件的内部列表:

criteria = [True, True, False]

Where a True criterion would mean that the element should be 'maximized' and a False criterion would mean that the element should be 'minimized'. True标准意味着元素应该“最大化”,而False标准意味着元素应该“最小化”。

Expected Output:预期输出:

Considering the above case, if the values to be maximized are summed and set as the first value in a tuple, and the values to be minimized are summed and set as the second value in a tuple, the following would occur:考虑到上述情况,如果将要最大化的值相加并设置为元组中的第一个值,并且将要最小化的值求和并设置为元组中的第二个值,则会发生以下情况:

  • inner list 1: (4.0, 5.0)内部列表 1: (4.0, 5.0)
  • inner list 2: (8.0, 0.0)内部列表 2: (8.0, 0.0)
  • inner list 3: (3.0, 4.0)内部列表 3: (3.0, 4.0)

It is clear from the above example that inner list 2 should be the selection, as it has both the highest 'to be maximized' value (8.0) and the lowest 'to be minimized' value (0.0).从上面的示例中可以清楚地看出,内部列表 2应该是选择,因为它具有最高的“要最大化”值 (8.0) 和最低的“要最小化”值 (0.0)。

However, the real world data that I'm using is not always so clear-cut;然而,我使用的真实世界数据并不总是那么清晰。 the maximums and minimums may belong to different inner lists.最大值和最小值可能属于不同的内部列表。 In addition, these lists (both the inner and outer lists) are far longer than just three elements.此外,这些列表(内部列表和外部列表)远不止三个元素。

Current Method:当前方法:

I'm currently selecting a list by determining the difference between the first and second values of the above tuples, then selecting the inner list that exhibits the maximum difference, like so:我目前通过确定上述元组的第一个和第二个值之间的差异来选择一个列表,然后选择表现出最大差异的内部列表,如下所示:

def element_wise_iterable_selection(iterable: list[list[float]], criteria: list[bool | None]) -> int:
        
    differences = []
    
    for sublist in iterable:

        temporary_max_sum, temporary_min_sum = 0, 0

        for i, element in enumerate(sublist):

            if criteria[i]:

                temporary_max_sum += element

            if not criteria[i]:

                temporary_min_sum += element

        differences.append(abs(temporary_max_sum - temporary_min_sum))

    return differences.index(max(differences))

This method seems very 'thrown-together'.这种方法看起来很“合二为一”。 Is there a better / more pythonic way of doing this?有没有更好/更蟒蛇的方式来做到这一点? I was thinking that NumPy may have a method to handle cases like this.我在想 NumPy 可能有一种方法来处理这种情况。

By using the compress function from itertools and also avoiding creating a useless list of differences you can do that :通过使用 itertools 中的 compress 函数并避免创建无用的差异列表,您可以这样做:

from itertools import compress

def element_wise_iterable_selection(iterable: list[list[float]], criteria: list[bool]) -> int:
    maxDiff = (0,0)
    notCriteria = [not elem for elem in criteria]
    for index, sublist in enumerate(iterable):
        tempMaxSum = sum(compress(sublist, criteria))
        tempMinSum = sum(compress(sublist, notCriteria))
        if abs(tempMaxSum - tempMinSum) > maxDiff[0]:
            maxDiff = (abs(tempMaxSum - tempMinSum), index)
    return maxDiff[1]

list_of_lists = [[1.0, 3.0, 5.0], [3.0, 5.0, 0.0], [2.0, 1.0, 4.0]]
criteria = [True, True, False]  
print(element_wise_iterable_selection(list_of_lists, criteria))
def element_wise_iterable_selection(list_of_lists, criteria):
    def sort_helper(x):
        total = 0
        for index, value in enumerate(x):
            if criteria[index]:
                total += value
            else:
                total -= value
        return abs(total)

    sublist = sorted(list_of_lists, key=lambda x: sort_helper(x))[-1]
    return list_of_lists.index(sublist)

Output:输出:

>>> print(element_wise_iterable_selection(list_of_lists, criteria))
>>> 1

我不确定 NumPy,但你当然可以在 1-liner 中做到这一点

differences = [abs(sum([e for i, e in enumerate(sublist) if criteria[i]])-sum([e for i, e in enumerate(sublist) if not criteria[i]])) for sublist in list_of_lists]

Numpy does make it much easier. Numpy 确实让它变得容易多了。 This might not be the most elegant solution, but it works.这可能不是最优雅的解决方案,但它确实有效。 Since we are indexing 2d arrays, I changed your sample list_of_lists so that both axes are different, making it easier to follow.由于我们正在索引二维数组,因此我更改了您的示例 list_of_lists 以便两个轴不同,从而更容易理解。

import numpy as np
list_of_lists = [[1.0, 3.0, 5.0], [3.0, 5.0, 0.0], [2.0, 1.0, 4.0], [3.0, 0.0, 1.0]]
lol = np.array(list_of_lists)
dims = np.shape(lol)
criteria = [True, True, False]
mask = np.repeat(np.reshape(criteria, (1, dims[1])), dims[0], axis=0)

maxima = np.sum(lol* mask, axis=1)
minima = np.sum(lol* ~mask, axis=1)
differences = maxima - minima # add an np.abs if you need
print(np.argmax(differences))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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