获取密钥总数小于或等于X的前5个值

时间:2018-09-24 23:27:08

标签: python python-2.7

目前,我有一些人可以购买的物品清单,如下所示:

my_list = [
    ('Candy', 1.0, 20.5),
    ('Soda', 3.0, 10.25),
    ('Coffee', 1.2, 20.335),
    ('Soap', 1.2, 11.5),
    ('Spoon', 0.2, 2.32),
    ('Toast', 3.2, 12.335),
    ('Toothpaste', 3, 20.5),
    ('Creamer', .1, 5.5),
    ('Sugar', 2.2, 5.2),
]

每个项目都是这样设置的:

('Item Name', ItemCost, ItemValue)

我有一个列表拉出了前5名ItemValue的项目。

print nlargest(5, my_list, key=itemgetter(2))
>>> [
        ('Candy', 1.0, 20.5),
        ('Toothpaste', 3, 20.5),
        ('Coffee', 1.2, 20.335),
        ('Toast', 3.2, 12.335),
        ('Soap', 1.2, 11.5),
    ]

我正在尝试检索结果,得出前5名ItemValue中前5名ItemCost等于或小于6。

有什么建议吗?

9 个答案:

答案 0 :(得分:6)

您可以先进行过滤,然后在过滤后的列表中使用以下所有nlargest

f = [(a,b,c) for (a,b,c) in my_list if b <= 6]

但是对于这样的数据操作,pandas可能非常有用。以

为例
df = pd.DataFrame(my_list, columns=('ItemName', 'ItemCost', 'ItemValue'))

    ItemName    ItemCost    ItemValue
0   Candy       1.0         20.500
1   Soda        3.0         10.250
2   Coffee      1.2         20.335
3   Soap        1.2         11.500
4   Spoon       0.2         2.320
5   Toast       3.2         12.335
6   Toothpaste  3.0         20.500
7   Creamer     0.1         5.500
8   Sugar       2.2         5.200

>>> df[df.ItemCost <= 6]

    ItemName    ItemCost    ItemValue
0   Candy       1.0         20.500
1   Soda        3.0         10.250
2   Coffee      1.2         20.335
3   Soap        1.2         11.500
4   Spoon       0.2         2.320
5   Toast       3.2         12.335
6   Toothpaste  3.0         20.500
7   Creamer     0.1         5.500
8   Sugar       2.2         5.200

>>> df[df.ItemCost <= 6].nlargest(n=5, columns=['ItemValue'])


    ItemName    ItemCost    ItemValue
0   Candy       1.0         20.500
6   Toothpaste  3.0         20.500
2   Coffee      1.2         20.335
5   Toast       3.2         12.335
3   Soap        1.2         11.500

如果需要,您可以先获取nsmallest中的ItemCost,然后 然后获取nlargest

df.nsmallest(n=5, columns=['ItemCost']).nlargest(n=5, columns=['ItemValue'])    

    ItemName    ItemCost    ItemValue
0   Candy       1.0         20.500
2   Coffee      1.2         20.335
3   Soap        1.2         11.500
7   Creamer     0.1         5.500
4   Spoon       0.2         2.320

答案 1 :(得分:1)

不确定这是否是您的要求

我首先要从my_list创建5个元素的所有可能组合

itertools.combinations(my_list, 5)

然后,我将找到结果中所有可能的组合,其中总项目成本小于或等于6。

f = [element for element in itertools.combinations(my_list, 5) if  sum([e[1] for e in element]) <=6]

现在,我将找到itemValue总值最大的那个元素

h = [sum([g[2] for g in e]) for e in f]

最大itemValue的元素的索引为

index = h.index(max(h))

现在,您可以在f中找到该元素。

f[index]

我得到的答案是

 Candy        1.0  20.5
 Coffee       1.2  20.335
 Spoon        0.2  2.32
 Toothpaste   3    20.5
 Creamer      0.1  5.5

答案 2 :(得分:0)

首先,您要按ItemCost过滤列表:

  • 可以通过以下方式完成:filtered_generator = filter(lambda x: x[1] <= 6, my_list)

  • 或者以更类似于python的方式filtered_list = [x for x in my_list if x[1] <=6]

  • 要使其成为生成器来节省内存,只需使用括号而不是方括号即可。

然后您要获得n个最大的物品:

  • 您可以使用heapq.nlargestnlargest(5, filtered_iter, key=lambda x:x[2])
  • 或自己实现类似功能。

filtered_iter可以是列表,也可以是生成器之一。

答案 3 :(得分:0)

from operator import itemgetter
from itertools import combinations
from beautifultable import BeautifulTable

def pretty_print( lst):
    table = BeautifulTable()
    table.column_headers = ['Item Name','ItemCost','ItemValue']
    if lst:
        for item_specs in lst:
            table.append_row(item_specs)
        print(table)


def get_total_cost( lst):
    return sum(item_specs[1] for item_specs in lst)

def get_total_Value( lst):
    return sum(item_specs[2] for item_specs in lst)



def best_comb( item_list, number_of_items_to_pick, cost_constraint):


    k = number_of_items_to_pick

    item_list.sort(key=itemgetter(2), reverse=True) # sorting list by ItemValue

    k_top_value_item_lst = item_list[:5] # picking top k items from list

    total_cost = get_total_cost(k_top_value_item_lst)


    def generateCombinations( take_default_val_for_best_result = True):
        k_len_combination_list = list(combinations( item_list, k))

        if take_default_val_for_best_result:
            best_result = []# which meets total itemCost <= 6 condition and have highest total of ItemValue 
            best_result_sum = [0,0] # ItemCost, ItemValue    
        else:
            best_result = k_top_value_item_lst
            best_result_sum = [total_cost, get_total_Value(best_result)]


        best_alternative_lst = [] # if there are any other combination which offer same Value for Cost

        # ignore first comb as its been already suggested to user
        for comb in k_len_combination_list:

            temp_sum = [None,None]
            temp_sum[0] = get_total_cost( comb)
            reset_best = False

            if  temp_sum[0] <= cost_constraint:
                temp_sum[1] = get_total_Value( comb)

                if best_result_sum[1] < temp_sum[1]:
                    reset_best = True

                elif best_result_sum[1] == temp_sum[1]:
                    if temp_sum[0] < best_result_sum[0]:
                        reset_best = True
                    elif temp_sum[0] == best_result_sum[0]:
                        # since ItemValue as well as ItemCost are equivalent to best_result this comb is great alternative
                        if comb != tuple(best_result):
                            best_alternative_lst.append(comb)

                if reset_best:
                    best_result = comb
                    best_result_sum[1] = temp_sum[1]
                    best_result_sum[0] = temp_sum[0]

        print('Best Combination:')
        if best_result:
            pretty_print(best_result)
        else:
            print('not found')

        if gen_alternative:
            print('\nBest Alternative Combination:')
            if best_alternative_lst:
                for idx,alter_comb in enumerate( best_alternative_lst):
                    comb_id = idx+1
                    print('combination_id ',comb_id)
                    pretty_print(alter_comb)
            else:
                print('not found')


    if total_cost > cost_constraint:
        generateCombinations()

    else:
        if gen_alternative:
            generateCombinations(take_default_val_for_best_result = False)

        else:
            print('Best Combination:')
            pretty_print(k_top_value_item_lst)



my_list = [
    ('Candy', 2.0, 20.5),
    ('Soda', 1.5, 25.7 ), 
    ('Coffee', 2.4, 25.7 ),
    ('Soap', 1.2,20),
    ('Spoon',1.2,20 ), 
    ('Toast',1.2,22 ),
    ('Toothpaste',0.8, 20 ), 
    ('Creamer',0.8, 22),
    ('Sugar',2.0, 20.5 ),
]

gen_alternative = input('do you want to generate alternative combinations: y/n ')[0].lower() == 'y'

best_comb( my_list, 5, 6)

回答修改后的列表(以显示其他功能)

do you want to generate alternative combinations: y/n Y
Best Combination:
+------------+----------+-----------+
| Item Name  | ItemCost | ItemValue |
+------------+----------+-----------+
|    Soda    |   1.5    |   25.7    |
+------------+----------+-----------+
|   Toast    |   1.2    |    22     |
+------------+----------+-----------+
|  Creamer   |   0.8    |    22     |
+------------+----------+-----------+
|    Soap    |   1.2    |    20     |
+------------+----------+-----------+
| Toothpaste |   0.8    |    20     |
+------------+----------+-----------+

Best Alternative Combination:
combination_id  1
+------------+----------+-----------+
| Item Name  | ItemCost | ItemValue |
+------------+----------+-----------+
|    Soda    |   1.5    |   25.7    |
+------------+----------+-----------+
|   Toast    |   1.2    |    22     |
+------------+----------+-----------+
|  Creamer   |   0.8    |    22     |
+------------+----------+-----------+
|   Spoon    |   1.2    |    20     | <---
+------------+----------+-----------+
| Toothpaste |   0.8    |    20     |
+------------+----------+-----------+      

回答您的原始列表

Best Combination:
+------------+----------+-----------+
| Item Name  | ItemCost | ItemValue |
+------------+----------+-----------+
|   Candy    |   1.0    |   20.5    |
+------------+----------+-----------+
| Toothpaste |    3     |   20.5    |
+------------+----------+-----------+
|   Coffee   |   1.2    |  20.335   |
+------------+----------+-----------+
|  Creamer   |   0.1    |    5.5    |
+------------+----------+-----------+
|   Spoon    |   0.2    |   2.32    |
+------------+----------+-----------+

Best Alternative Combination:
not found

答案 4 :(得分:0)

不确定您要做什么,但是...
如果您尝试根据按最低成本排序的itemcost检索前x个(5或6),则可以尝试此操作。

x=5
sorted(my_list, key=lambda s : s[2])[:x]

This outputs the following:

[('Spoon', 0.2, 2.32),
('Sugar', 2.2, 5.2),
('Creamer', 0.1, 5.5),
('Soda', 3.0, 10.25),
('Soap', 1.2, 11.5)]

答案 5 :(得分:0)

from itertools import combinations
from functools import reduce

def get_valid_combs(lis):
    "find all combinations that cost less than or equal to 6"

    for i in combinations(lis, 5):
        if reduce(lambda acc, x: acc + x[1], list(i), 0) <= 6:
            yield list(i)

my_list = [
    ('Candy', 1.0, 20.5),
    ('Soda', 3.0, 10.25),
    ('Coffee', 1.2, 20.335),
    ('Soap', 1.2, 11.5),
    ('Spoon', 0.2, 2.32),
    ('Toast', 3.2, 12.335),
    ('Toothpaste', 3, 20.5),
    ('Creamer', .1, 5.5),
    ('Sugar', 2.2, 5.2),
]

# find all valid combinations which  cost less than 6
valid_combinations = [i for i in get_valid_combs(my_list)]

#top_combinations_sorted = sorted(valid_combinations, key=lambda y: reduce(lambda acc, x: acc + x[2], [0]+y))

# of the valid combinations get the combination with highest total value
best_combination = max(valid_combinations, key=lambda y: reduce(lambda acc, x: acc + x[2], y, 0))

print(best_combination)

输出:

[('Candy', 1.0, 20.5), ('Coffee', 1.2, 20.335), ('Spoon', 0.2, 2.32), ('Toothpaste', 3, 20.5), ('Creamer', 0.1, 5.5)]

答案 6 :(得分:0)

from itertools import combinations

...

total_cost = lambda item: int(sum(c for _, c, _ in item) <= 6) * sum(v for _, _ , v in item)
chosen = max(combinations(my_list, 5), key=total_cost)

Max可以接收指定最大条件的函数。

total_cost函数的int(sum(c表示_,c,_项)<= 6)部分如果组合的总成本小于或等于6则为1,否则为0. < / p>

然后将这部分乘以总值。

combinations(my_list,5)检索具有5个项目的my_list项目的所有可能组合。

打印所选的元素:

('Candy', 1.0, 20.5)
('Coffee', 1.2, 20.335)
('Spoon', 0.2, 2.32)
('Toothpaste', 3, 20.5)
('Creamer', 0.1, 5.5)

答案 7 :(得分:0)

首先过滤列表:

print nlargest(5, [item for item in my_list if item[1]<=6], key=itemgetter(2))

您也可以使用sorted:

sorted([item for item in my_list if item[1]<=6], key=lambda x: x[1], reverse=True)[:5]

上面的过滤器过滤出 ItemCost 大于6的项目,对根据 ItemCost 降序排列的列表进行排序,然后返回前5个元素

答案 8 :(得分:0)

首先使用applicationId,我们可以从combinations获得所有5的可能组合。从这里开始,我们可以使用my_list并仅返回总filter小于或等于ItemCost的组合。最后,我们根据哪个组的总数最高6进行排序,然后选择最大的一组ItemValue,我们可以使用l2[-1],那么它将是reverse = True

从itertools导入组合

l2[0]
l = list(combinations(my_list, 5))
l1 = list(filter(lambda x: sum([i[1] for i in x]) < 6, l))
l2 = sorted(l1, key=lambda x: sum([i[2] for i in x]))
print(l2[-1])