Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 获取三维列表中唯一元素的最低索引的高效算法_Python_Algorithm_Sorting - Fatal编程技术网

Python 获取三维列表中唯一元素的最低索引的高效算法

Python 获取三维列表中唯一元素的最低索引的高效算法,python,algorithm,sorting,Python,Algorithm,Sorting,设置 给出一个列表列表,如以下列表: lll = [] for _ in range(5): ll = [random.sample(range(1, 20), 5), random.sample(range(1, 20), 5), random.sample(range(1, 20), 5)] lll.append(ll) 这可能会给出: [[[1, 15, 12], [8, 5, 13], [1, 9, 12]], [[4, 1,

设置

给出一个列表列表,如以下列表:

lll = []
for _ in range(5):  
    ll = [random.sample(range(1, 20), 5),
         random.sample(range(1, 20), 5),
         random.sample(range(1, 20), 5)]
    lll.append(ll)
这可能会给出:

[[[1, 15, 12], [8, 5, 13], [1, 9, 12]],
 [[4, 1, 19], [11, 18, 3], [8, 14, 6]],
 [[17, 8, 4], [1, 16, 3], [19, 13, 11]]]
最终目标

我希望获得元素出现的最低索引,并以字典的形式返回此输出,例如:

{0: {1, 17, 19, 4, 8, 11}, 1: {5, 9, 13, 14, 15, 16, 18}, 2: {3, 12, 6}}
例如,在上面的
lll
中,
8
出现在3个子列表中。但它在单个子列表中的最低位置是
0
,这就是为什么它会出现在最后一个字典中的
0

约束

{0: [1, 8, 4, 19, 11, 17], 1: [15, 5, 13, 9, 18, 14, 16], 2: [12, 3, 6]}
{0: {1, 4, 8, 11, 17, 19}, 1: {5, 9, 13, 14, 15, 16, 18}, 2: {3, 12, 6}}
我必须迭代
lll
(我的用例假设我不知道完整的
lll
)。因此,
遍历\u dct
将随着时间的推移而增加。上述
lll
是用于演示的虚拟数据

工作解决方案

目前的方法是有效的,但我相信它会更有效

traversal_dct = {}

for ll in lll:

    llT = [*map(list, zip(*ll))]

    for i,xs in enumerate(llT):
        if i not in traversal_dct.keys():
            traversal_dct[i] = set()
        traversal_dct[i] = traversal_dct[i].union(set(xs))

    for i1,key1 in enumerate(traversal_dct.keys()):
        for i2,key2 in enumerate(traversal_dct.keys()):
            if i2 > i1:
                traversal_dct[i2] = traversal_dct[i2] - traversal_dct[i1]

我觉得你让事情变得更难了

不管你有多少尺寸,把它展平到2D;您没有使用比三元素列表更深层的内容

现在只需列出集合,每个维度中的元素

e = [set(row[col] for row in 2d_list) for col in range(len(2d_list[0]))]
现在,从这些集合中减去之前的集合

e[1] -= e[0]
e[2] -= e[0] + e[1]

。。。您还可以在循环中对其进行参数化。

IIUC,您可以执行以下操作:

lll = [[[1, 15, 12], [8, 5, 13], [1, 9, 12]],
       [[4, 1, 19], [11, 18, 3], [8, 14, 6]],
       [[17, 8, 4], [1, 16, 3], [19, 13, 11]]]


def flatten(lst):
    """Flatten an arbitrary nested list, if the element is not a list return its position"""
    for i, e in enumerate(lst):
        if isinstance(e, list):
            yield from flatten(e)
        else:
            yield (i, e)


# create a dictionary of value -> min-pos
d = {}
for i, e in flatten(lll):
    d[e] = i if e not in d else min(d[e], i)

# reverse the dictionary
reverse = {}
for key, value in d.items():
    reverse.setdefault(value, []).append(key)

print(reverse)
输出

{0: [1, 8, 4, 19, 11, 17], 1: [15, 5, 13, 9, 18, 14, 16], 2: [12, 3, 6]}
{0: {1, 4, 8, 11, 17, 19}, 1: {5, 9, 13, 14, 15, 16, 18}, 2: {3, 12, 6}}
如果要将列表转换为集合,请执行以下操作:

result = {key : set(value) for key, value in reverse.items()}
print(result)
输出

{0: [1, 8, 4, 19, 11, 17], 1: [15, 5, 13, 9, 18, 14, 16], 2: [12, 3, 6]}
{0: {1, 4, 8, 11, 17, 19}, 1: {5, 9, 13, 14, 15, 16, 18}, 2: {3, 12, 6}}

您可以维护两个词典:

  • 一个用于跟踪每个值的最小索引
  • 一个用于跟踪索引->值集映射
然后,对于您检索到的每个
ll
,您可以根据(展平的)
ll
的长度在时间上进行更新,而无需重建整个
遍历字典:

from collections import defaultdict

min_pos = defaultdict(int)
traversal_dict = defaultdict(set)

for ll in lll:  # assume this is streamed / iterated
    for l in ll:
        for (i, val) in enumerate(l):
            if val not in min_pos:  # O(1) to update both dictionaries
                min_pos[val] = i
                traversal_dict[i].add(val)
            elif i < min_pos[val]:
                traversal_dict[min_pos[val]].remove(val)
                min_pos[val] = i
                traversal_dict[i].add(val)
    print traversal_dict  # retrieve answer after each iteration

您需要多久返回一次答案?是每次迭代还是在您完成对
lll
的所有元素的迭代之后?始终是3级深度?@滑块每次iteration@Daniel_Mesejo,不,它是可变的,这几乎让我想起了一个小堆,所以如果你需要一直把它泡起来,我会用这种方法。如果不是,您仍然需要访问完整的项目集,因此它的运行时仍然为n,其中n是单元格/项目的完整计数。