如何比较列表中的两个元素以找到最低价格?

2024-09-29 23:19:25 发布

您现在位置:Python中文网/ 问答频道 /正文

给定两个列表availprod,其中avail是一个包含电话号码、商品代码和价格的列表,prod是一个包含商品代码和名称的列表,如果avail中的商品代码也在prod(产品列表)中,我想尝试找到给定商品代码的最低价格,返回列表列表,其中提供每个项目的电话号码、价格和项目代码

我尝试了下面的代码,但它只是附加了每个j[2],这是可以理解的(它附加了所有的价格,只打印最小值)。我不知道如何实现这一点

def best_prices(avail,prod):
    lowest_prices=[]
    price_list=[]
    for i in prod:
        for j in avail:
            if i[0]==j[1]:
                price_list.append(j[2])
                store_min=min(price_list)
                print(store_min)
                print(price_list)
                lowest_prices.append(j)
    return lowest_prices

列表的格式如下:

avail = [
    ['phone number', 'item code', 'price'],
    ...
] 

prod = [
    ['item code', 'name of product'],
    ...
]

以下是一些输入示例:

prod = [
    ['123456789', '2L 2% Vitali Milk'],
    ['123456798', '1L 2% Vitali Milk'],
    ['456392452', '70% Cocoa Zimbra Chocolate'],
    ['456123490', 'Zimbra Milk Chocolate'],
    ['634590221', 'Onion flavour chips'],
    ['634599011', 'Vinegar flavour chips'],
    ['780123678', 'Sliced white bread'],
    ['780432109', 'Sliced whole wheat bread'],
    ['809001234', '2L Orange Juice'],
    ['808765432', '2L Apple Juice']
]

avail = [
    ['123456789', '7807890123', '2.58'],
    ['123456789', '7804922860', '2.99'],
    ['456392452', '7807890123', '2.11'],
    ['456123490', '7804922860', '3.10'],
    ['808765432', '7809876543', '4.10']
]

我想让我的程序为每个匹配的商品代码查找avail以找到最低价格,然后返回包含最低价格电话号码和商品代码的列表

因此,对于:

prod = [
    ['123456789', '2L 2% Vitali Milk']
]

avail = [
    ['123456789', '7807890123', '2.58'],
    ['123456789', '7804922860', '2.99'],
    ['456392452', '7807890123', '2.11']
]

我想返回:

new_list = [
    ['2.58', '123456789', '7807890123']
]

Tags: 项目代码列表电话号码价格prodminprice
3条回答

以下是评论中的答案和解释:

prod = [
    ['123456789', '2L 2% Vitali Milk'],
    ['123456798', '1L 2% Vitali Milk'],
    ['456392452', '70% Cocoa Zimbra Chocolate'],
    ['456123490', 'Zimbra Milk Chocolate'],
    ['634590221', 'Onion flavour chips'],
    ['634599011', 'Vinegar flavour chips'],
    ['780123678', 'Sliced white bread'],
    ['780432109', 'Sliced whole wheat bread'],
    ['809001234', '2L Orange Juice'],
    ['808765432', '2L Apple Juice']
]
avail = [
    ['123456789', '7807890123', '2.58'],
    ['123456789', '7804922860', '2.99'],
    ['456392452', '7807890123', '2.11'],
    ['456123490', '7804922860', '3.10'],
    ['808765432', '7809876543', '4.10']
]

# you can keep track of the best record for a given product code using a dict
result = {}

# since prod is really just a mapping from product code to product name, it 
# also works well as a dict
prod_d = {p[0]: p[1] for p in prod}

# now, it's easy to construct the result from avail:
# (the cast to tuple allows for spreading into nicely named variables)
for pc, phone, price in (tuple(a) for a in avail):
    # using -1 as price will still be the last element
    if pc not in result or price < result[pc][-1]:
        result[pc] = [prod_d[pc], phone, price]
print(result)

# if you prefer a list after all:
result = [[pc, prod, phone, price] for pc, (prod, phone, price) in result.items()]
print(result)

结果:

{'123456789': ['2L 2% Vitali Milk', '7807890123', '2.58'], '456392452': ['70% Cocoa Zimbra Chocolate', '7807890123', '2.11'], '456123490': ['Zimbra Milk Chocolate', '7804922860', '3.10'], '808765432': ['2L Apple Juice', '7809876543', '4.10']}
[['123456789', '2L 2% Vitali Milk', '7807890123', '2.58'], ['456392452', '70% Cocoa Zimbra Chocolate', '7807890123', '2.11'], ['456123490', 'Zimbra Milk Chocolate', '7804922860', '3.10'], ['808765432', '2L Apple Juice', '7809876543', '4.10']]

只是解决方案:

result = {}
prod_d = {p[0]: p[1] for p in prod}

for pc, phone, price in (tuple(a) for a in avail):
    if pc not in result or price < result[pc][-1]:
        result[pc] = [prod_d[pc], phone, price]

result_list = [[pc, prod, phone, price] for pc, (prod, phone, price) in result.items()]

我能给你们的第一个建议是对变量使用有意义的名称

考虑到这一点,我提出以下解决方案:

# just for a nice output
from pprint import pprint


def find_best_prices(products, vendors):
    prices = {}

    for product_code, product_name in products:
        for vendor_product_code, vendor_phone, vendor_product_price in vendors:
            if product_code not in prices:
                prices[product_code] = {}
            if product_code == vendor_product_code:
                if prices[product_code]:
                    if prices[product_code]['price'] > vendor_product_price:
                        prices[product_code] = {
                            'vendor_price': vendor_product_price,
                            'vendor_phone': vendor_phone
                        }
                else:
                    prices[product_code] = {
                        'vendor_price': vendor_product_price,
                        'vendor_phone': vendor_phone
                    }

    return prices


products = [
    ['123456789', '2L 2% Vitali Milk'],
    ['123456798', '1L 2% Vitali Milk'],
    ['456392452', '70% Cocoa Zimbra Chocolate'],
    ['456123490', 'Zimbra Milk Chocolate'],
    ['634590221', 'Onion flavour chips'],
    ['634599011', 'Vinegar flavour chips'],
    ['780123678', 'Sliced white bread'],
    ['780432109', 'Sliced whole wheat bread'],
    ['809001234', '2L Orange Juice'],
    ['808765432', '2L Apple Juice']
]

vendors = [
    ['123456789', '7807890123', '2.58'],
    ['123456789', '7804922860', '2.99'],
    ['456392452', '7807890123', '2.11'],
    ['456123490', '7804922860', '3.10'],
    ['808765432', '7809876543', '4.10']
]

pprint(find_best_prices(products, vendors))

上述代码将产生以下输出:

{'123456789': {'vendor_phone': '7807890123', 'vendor_price': '2.58'},
 '123456798': {},
 '456123490': {'vendor_phone': '7804922860', 'vendor_price': '3.10'},
 '456392452': {'vendor_phone': '7807890123', 'vendor_price': '2.11'},
 '634590221': {},
 '634599011': {},
 '780123678': {},
 '780432109': {},
 '808765432': {'vendor_phone': '7809876543', 'vendor_price': '4.10'},
 '809001234': {}}

上面的代码处理逻辑中的关系“先见先赢”。这意味着,如果有两个vendors具有相同的vendor_product_price用于相同的vendor_product_code,则第一个vendor出现在报告中

要将该行为更改为“最后一次看到,最后一次赢”,请将比较行中的>替换为>=,如下所示:

if prices[product_code]['price'] > vendor_product_price:

最后,另一种策略是基于vendor_product_price消除重复vendors,保持最低价格,然后将products与结果列表关联

以下是这一想法的实施情况:

def find_best_prices(products, vendors):
    prices = {}
    for product, phone, price in vendors:
        if product not in prices:
            prices[product] = {
                'vendor_phone': phone,
                'vendor_price': price
            }
        else:
            if prices[product]['vendor_price'] > price:
                prices[product] = {
                    'vendor_phone': phone,
                    'vendor_price': price
                }

    for product, _ in products:
        if product not in prices:
            prices[product] = {}

    return prices

有很大的改进空间,但这是故意留下来的。我愿意说教,而不是讲求效率

下面是简单、清晰、非常符合Python的问题解决方案

我假设价格总是在avail列表中的最后一个位置,项目代码总是在availprod列表中的第一个位置。这很明显,但要注意列表的元素顺序

解决方案:

avail = [
    ['item code', 'phone number', 'price'],
    ...
]

prod = [
    ['item code', 'name of product'],
    ...
]

def best_prices(avail, prod):
    # find only items from available with item code present in products
    items = [
        av for av in avail if any(av[0] == pr[0] for pr in prod)
    ]
    # check if any item is available
    if not items:
       return None
    # sort items by price (ascending) and return first item
    return sorted(items, key=lambda x: x[2])[0]

示例:

>>> prod = [
...     ['123456789', '2L 2% Vitali Milk'],
... ]
>>> avail = [
...     ['123456789', '7807890123', '2.58'],
...     ['123456789', '7804922860', '2.99'],
...     ['456392452', '7807890123', '2.11'],
... ]
>>> print(best_prices(avail, prod))
['123456789', '7807890123', '2.58']

如果返回列表的元素顺序对您来说非常重要(但我不这么认为),您可以重新排序(反转):

def best_prices(avail, prod):
    ....
    return sorted(items, key=lambda x: x[2])[0][::-1]

奖金:

Extreme one liner完全按照您的预期工作:

>>> print((sorted([a for a in avail if any(a[0] == p[0] for p in prod)], key=lambda x: x[2]) or [None])[0][::-1])
['2.58', '7807890123', '123456789']

免责声明:在代码中使用这样的一行程序可能不是一个好主意

相关问题 更多 >

    热门问题