【问题标题】:Given a list of lists in Python, return the maximum length uniquely-valued sublists给定 Python 中的列表列表,返回最大长度的唯一值子列表
【发布时间】:2013-01-11 00:14:43
【问题描述】:

我在 Python 中有以下列表:

l = [[2], [3], [2, 2], [5], [2], [3], [7], [2, 2, 2], [3, 3], [2], [5], [11], [2, 2], [3], [13], [2], [7], [3], [5], [2, 2, 2, 2], [17], [2], [3, 3], [19], [2, 2], [5]]

我想编写一个函数来返回最大长度的唯一值子列表。在这种情况下,函数将返回:

l = [[5], [7], [3, 3], [11], [13], [2, 2, 2, 2], [17], [19]]

我仍然是 python 的初学者,但是我对如何编写这样的函数知之甚少。我得到的最远的是弄清楚我可以通过使用嵌套循环来迭代子列表。但从我对 Python 的了解来看,似乎必须有一些比使用循环更简单的方法来返回我正在寻找的列表。

更新:

这是我对代码所做的:解决项目 euler #5,非暴力方式!

我确信这段代码可以重构,但无论如何。

谢谢你们的帮助,伙计们。 itemgetter 正是我所需要的。

#!/usr/bin/python
# coding = UTF-8

import argparse, sys, math
from itertools import groupby
from collections import defaultdict
from operator import itemgetter

parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='?')
args = parser.parse_args()
if args:
   intinput = int(sys.argv[1])
elif not sys.stdin.isatty():
    intinput = int(sys.stdin.read())
else:
    parser.print_help()

def prime_factorize(n):
    factors = []
    number = math.fabs(n)

    while number > 1:
        factor = get_next_prime_factor(number)
        factors.append(factor)
        number /= factor

    if n < -1: 
        factors[0] = -factors[0]

    return factors

def get_next_prime_factor(n):
    if n % 2 == 0:
        return 2

    for x in range(3, int(math.ceil(math.sqrt(n)) + 1), 2):
        if n % x == 0:
            return x

    return int(n)


def mkfactors(n):
  tpf = []
  for i in range(n+1):
    tpf.extend(prime_factorize(i))
  return tpf

l = [list(g) for k,g in groupby(mkfactors(intinput))]

m = [max(g) for _,g in groupby(sorted(l,key=itemgetter(0)),key=itemgetter(0))]


prod = 1

for list in m:
  for element in list:
    prod *= element

print prod

【问题讨论】:

  • 贴出你试过的代码。
  • 只有我,还是我看到素数?
  • 请删除 -ve 投票,他已经解决了他的问题并收到了很多很好的回应。
  • +1:这是一个非常合理的问题。

标签: python list nested


【解决方案1】:

如果你知道每个子列表都有相同的元素,你可以这样做:

l = [[2], [3], [2, 2], [5], [2], [3], [7], [2, 2, 2], [3, 3], [2], [5], [11], [2, 2], [3], [13], [2], [7], [3], [5], [2, 2, 2, 2], [17], [2], [3, 3], [19], [2, 2], [5]]

from collections import defaultdict

my_dict = defaultdict(list)

for ele in l:
    if len(my_dict[ele[0]]) < len(ele):
        my_dict[ele[0]] = ele

结果:

>>> my_dict.values()
[[2, 2, 2, 2], [3, 3], [5], [7], [11], [13], [17], [19]]

【讨论】:

    【解决方案2】:

    这里最简单的做法是使用使问题变得简单的数据结构,然后您总是可以在事后转换回来。

    例如,dict 将键(质数)映射到长度(指数)很容易。所以:

    >>> l = [[2], [3], [2, 2], [5], [2], [3], [7], [2, 2, 2], [3, 3], [2], [5], [11], [2, 2], [3], [13], [2], [7], [3], [5], [2, 2, 2, 2], [17], [2], [3, 3], [19], [2, 2], [5]]
    >>> d = {}
    >>> for sublist in l:
    ...     value, count = sublist[0], len(sublist)
    ...     if count > d.get(value, 0):
    ...         d[value] = count
    >>> d
    {2: 4, 3: 2, 5: 1, 7: 1, 11: 1, 13: 1, 17: 1, 19: 1}
    

    如何将其转回lists 的list 应该很明显,所以我将把它留给你。

    请注意,这会丢失订单,但您可以使用OrderedDict 轻松解决此问题。它还丢失了list 身份——例如,您最后返回的[2, 2, 2, 2]等于,但与原始@987654328 不同相同 @。但这也很容易解决——只需直接存储sublist 而不是使用count。无论如何,我认为这些都与您的问题无关。

    【讨论】:

    • 请注意,由于散列算法,您不会丢失订单。
    • @Marcin:实际上,由于散列算法,您确实失去了顺序——你最终得到了 sorted 顺序。但无论哪种方式,语言都不能保证这一点,在当前 CPython 实现的这个数字范围内,它恰好是正确的。
    【解决方案3】:
    from itertools import groupby
    from operator import itemgetter
    
    [max(g) for _,g in groupby(sorted(l),key=itemgetter(0))]
    

    出局:

    [[2, 2, 2, 2], [3, 3], [5], [7], [11], [13], [17], [19]]
    

    【讨论】:

      【解决方案4】:
      l = [[2], [3], [2, 2], [5], [2], [3], [7], [2, 2, 2], [3, 3], [2], [5], [11], [2, 2], [3], [13], [2], [7], [3], [5], [2, 2, 2, 2], [17], [2], [3, 3], [19], [2, 2], [5]]
      l = [max(i for i in l if j in i) for j in (2, 3, 5, 7, 11, 13, 17, 19)]
      print(l)
      # [[2, 2, 2, 2], [3, 3], [5], [7], [11], [13], [17], [19]]
      

      我猜这只是一个带有嵌套 for 循环的列表推导,但它工作正常。

      【讨论】:

        【解决方案5】:

        使用collections.Countersets

        In [47]: s=set([x[0] for x in lis])
        
        In [48]: c=[Counter(x) for x in lis]
        
        In [49]: [max(c,key=lambda y:y[x]) for x in s]
        Out[49]: 
        [Counter({2: 4}),
         Counter({3: 2}),
         Counter({5: 1}),
         Counter({7: 1}),
         Counter({11: 1}),
         Counter({13: 1}),
         Counter({17: 1}),
         Counter({19: 1})]
        

        另一种方式:

        In [64]: from collections import defaultdict
        
        In [65]: d=defaultdict(list)
        
        In [66]: for x in lis:
            d[x[0]].append(len(x))
           ....:     
        
        In [67]: [[x]*max(y) for x,y in d.items()]
        Out[67]: [[2, 2, 2, 2], [3, 3], [5], [7], [11], [13], [17], [19]]
        

        【讨论】:

        • @Marcin 试着去理解它。
        • 如果这不应该被理解,那就不是答案。
        • 任何不重要的答案都没有解释它是如何工作的 - 因为从长远来看它并没有真正帮助任何人。
        【解决方案6】:

        一个简单的解决方案是将排序后的列表转换为以键为列表的第一个元素的字典,最终将根据键删除重复项。

        >>> {e[0]: e for e in sorted(l)}.values()
        [[2, 2, 2, 2], [3, 3], [5], [7], [11], [13], [17], [19]]
        

        对于 Python 版本

        >>> dict((e[0], e) for e in sorted(l)).values()
        [[2, 2, 2, 2], [3, 3], [5], [7], [11], [13], [17], [19]]
        

        【讨论】:

        • 很少使用的dict理解!当然,这在低于 2.7 的版本中不起作用。
        • @Marcin:当然,你总是可以在构建类型中使用 dict 来达到相同的结果。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-20
        相关资源
        最近更新 更多