【问题标题】:Get list based on occurrences in unknown number of sublists根据未知数量的子列表中的出现获取列表
【发布时间】:2011-09-13 06:50:25
【问题描述】:

我正在寻找一种方法,将包含列表(以下a)的列表制作成具有两个条件的单个列表(以下b):

  1. 新列表 (b) 的顺序基于该值在 a 中的某些列表中出现的次数。
  2. 一个值只能出现一次

基本上把a变成b

a = [[1,2,3,4], [2,3,4], [4,5,6]]
# value 4 occurs 3 times in list a and gets first position
# value 2 occurs 2 times in list a and get second position and so on...
b = [4,2,3,1,5,6]

我认为可以使用set 和一些列表魔术来做到这一点。但是当a 可以包含任意数量的列表时,我无法理解它。 a 列表是根据用户输入创建的(我猜它可以包含 1 - 20 个列表,每个列表中最多包含 200-300 个项目)。

我尝试与[set(l) for l in a] 类似,但不知道如何执行set(l) & set(l).... 以获取所有匹配的项目。

如果没有for 循环迭代子列表计数 * 子列表时间中的项目,是否可能?

【问题讨论】:

  • 你能更详细地描述一下你是如何从a 得到b 的吗?我无法解析您的第一句话。
  • 更新了问题以澄清它。希望我让自己更清楚一点。
  • 我认为这是有道理的。所以[['a','b','c'], ['b'], ['c']] 会映射到['b','c','a']。在这种情况下,'b''c' 的顺序是否重要?
  • @Wilduck:准确地说。而'b''c' 的顺序无关紧要

标签: python list


【解决方案1】:

我认为这可能是您最接近的:

from collections import defaultdict

d = defaultdict(int)

for sub in outer:
  for val in sub:
    d[val] += 1

print sorted(d.keys(), key=lambda k: d[k], reverse = True)
# Output: [4, 2, 3, 1, 5, 6]

出现相同次数的元素的顺序可能不确定 - d.keys() 的输出没有排序。

【讨论】:

  • 非常感谢,工作完全符合我的要求!好奇,你知道它是如何处理大列表的吗?它可以在 [[30n], [140n]] 列表中找到。
  • @fredrik - 它应该可以很好地支撑。中间字典的生成不会超过必要的循环,并且是 O(n)。排序时间将取决于不同值的总数,但 python 的内置排序算法非常巧妙。除非您正在处理非常大的子列表或大量不同的条目,否则应该没问题。这实际上是我对其他答案之一的主要疑虑 - -sum(x.count(y) for x in a) 是一个非常繁重的计算,有很多隐含的循环。
【解决方案2】:
import itertools
all_items = set(itertools.chain(*a))
b = sorted(all_items, key = lambda y: -sum(x.count(y) for x in a))

【讨论】:

  • 这很简洁,但-sum(x.count(y) for x in a)) 相当昂贵,不是吗?
  • -1 在几千个列表和几千个列表上试试这个; defaultdict 要好很多
  • @Ethan,是的。虽然 collection.Counter 更好。
  • @Ethan,不。我可能会,但我安装的 python 版本不够新。
【解决方案3】:

试试这个 -

a = [[1,2,3,4], [2,3,4], [4,5,6]]
s = set()
for l in a:
    s.update(l)
print s 
#set([1, 2, 3, 4, 5, 6])
b = list(s)

这会将每个列表添加到集合中,这将为您提供所有列表中所有元素的唯一集合。如果那是你所追求的。

编辑。要保留原始列表中元素的顺序,您不能使用集合。

a = [[1,2,3,4], [2,3,4], [4,5,6]]
b = []
for l in a:
    for i in l:
        if not i in b:
            b.append(i)
print b
#[1,2,3,4,5,6] - The same order as the set in this case, since thats the order they appear in the list

【讨论】:

  • 几乎(有点在路上)。但我需要b 的顺序基于a 中的出现次数。我更新了问题
  • 啊,那么你应该做基本相同的事情,但使用 dict 而不是 set。 a = [[1,2,3,4], [2,3,4], [4,5,6]] s = defaultdict(0) for l in a: for item in l: s[item] = s[item] + 1 print s #set([1, 2, 3, 4, 5, 6]) b = [pair[0] for pair in sorted(s.items(), key = lambda pair:pair[ 1]]
  • 根据您更新的关于基于数字出现次数的顺序的问题,下面的答案有它。
【解决方案4】:
import itertools
from collections import defaultdict

def list_by_count(lists):
    data_stream = itertools.chain.from_iterable(lists)
    counts = defaultdict(int)
    for item in data_stream:
        counts[item] += 1
    return [item for (item, count) in 
            sorted(counts.items(), key=lambda x: (-x[1], x[0]))]

在排序键中包含 x[0] 可确保具有相同计数的项目也处于某种序列中。

【讨论】:

    猜你喜欢
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多