【问题标题】:Comprehension to find the min in a dict理解在字典中找到最小值
【发布时间】:2018-09-23 16:50:48
【问题描述】:

我对一件事感到好奇:

我有一个字典,例如,以汽车为键,以速度为值。现在,我想找到具有最低值的键。

car_dict = {'mercedes': 200, 'fiat': 100, 'porsche': 300, 'rocketcar': 600}

我知道这段代码适用于 O(1)

car_value = list(car_dict.values())
car_key = list(car_dict.keys())
min_stats = min(car_value)
print(car_key[car_value.index(min_stats)]) 

这个也是 O(n)

keys = []
values = []
for name, value in car_dict.items():
    keys.append(name)
    values.append(value)

min_value = min(values)
print(keys[values.index(min_value)])

我目前正在努力更好地理解推导式,因此,我的问题是是否有可能通过列表推导式解决这个问题。

我在想这样的事情

worst = {name for name, stats in car_dict if min(stats)}

但是,我想我仍然误解了if 部分中的某些内容。

顺便说一句,如果我对上述大 O 复杂性的信念有误,请纠正我。

非常感谢!

【问题讨论】:

  • I know this code works with O(1) 不正确。 list(car_dict.values()) 需要迭代所有值,因此是 O(n)。
  • 第一个块在O(1) 中真的有效吗?
  • 谢谢! @jpp 不知道

标签: python list dictionary list-comprehension


【解决方案1】:

我知道这段代码适用于 O(1):

car_value = list(car_dict.values())

这是不正确的。要从视图中形成列表,您必须遍历所有值。此操作的时间复杂度为 O(n)。

通常,不需要创建键和值列表。避免这些操作,因为它们很昂贵。

注意min可以直接作用于dict.items,这是一个键值对的视图。仅当您只有一辆具有最小值的汽车时才建议这样做:

car, value = min(car_dict.items(), key=lambda x: x[1])  # (fiat, 100)

由于字典不被认为是有序的(除非您使用的是 Python 3.7),因此对于重复的最小值,结果将不确定。在这种情况下,您可以计算最小值,然后使用列表推导:

min_val = min(car_dict.values())
min_cars = [car for car, value in car_dict.items() if value == min_val]  # ['fiat']

您还可以使用next 和生成器表达式来提取第一辆这样的汽车:

min_car_first = next(car for car, value in car_dict.items() if value == min_val)

当然,在单车具有最小值的情况下,这将给出与第一个解决方案min(car_dict.items(), ...)相同的结果。

【讨论】:

  • 谢谢@jpp!!真的很全面!
【解决方案2】:

您无法在比线性时间更快的时间内解决此问题,但您可以在线性时间内一次性解决

min_speed = None
that_car = None
for car,speed in car_dict.items():
    if min_speed is None or speed < min_speed:
        that_car, min_speed = car, speed
that_car
#'fiat'

【讨论】:

    【解决方案3】:

    您可以将键的值与值的最小值进行比较

    worst = [i for i in car_dict if car_dict[i] == min(car_dict.values())]
    

    【讨论】:

    • 您需要将d 替换为car_dict
    • @Bazingaa 我在 vim 中使用 d,照原样复制,替换
    • @vash_the_stampede 谢谢!
    • @Bazingaa haha​​hah wow nice catch,我总是忘记转换回 OP 命名系统我喜欢短变量名,我知道你必须有相同的答案,你通常有一些与 mysefl 非常相似的东西
    • @vash_the_stampede:这就是我没有发帖的原因。我是列表推导的粉丝;)
    【解决方案4】:

    好吧,我不确定这个的运行时间是多少,但你可以试试它对我有用:

    >>> d = {'mercedes': 200, 'fiat': 100, 'porsche': 300, 'rocketcar': 600}
    >>> d.items()
    [('mercedes', 200), ('fiat', 100), ('porsche', 300) , ('rocketcar',600)]
    >>> # find the minimum by comparing the second element of each tuple
    >>> min(d.items(), key=lambda x: x[1]) 
    ('fiat', 100)
    

    【讨论】:

      【解决方案5】:

      这个怎么样:

      car_dict = {'mercedes': 200, 'fiat': 100, 'porsche': 300, 'rocketcar': 600}
      min_car = {}
      for car in car_dict:
          if not min_car or car_dict[car] < min_car['speed']:
              min_car['name'] = car
              min_car['speed'] = car_dict[car]
      print(min_car)
      

      【讨论】:

        【解决方案6】:

        问题是你不应该用推导来解决这个问题,因为你不能在推导中进行赋值。迭代字典,您可以在单遍中找到最小值:

        car_iterator = iter(car_dict.items())
        slowest_car, min_speed = next(car_list)
        for car, speed in car_iterator:
            if speed < min_speed:
                slowest_car = car
        

        【讨论】:

          猜你喜欢
          • 2015-01-16
          • 2020-07-26
          • 2021-07-16
          • 1970-01-01
          • 2019-06-07
          • 1970-01-01
          • 1970-01-01
          • 2015-07-18
          • 2019-02-09
          相关资源
          最近更新 更多