如何根据python中的直接前导列表获取完整的前驱列表?

时间:2018-05-10 13:33:10

标签: python python-3.x python-2.7

我的问题与露天矿中矿石块的开采有关。如下所述,块具有pecedência的关系。 在这个表示中我们有6个块,其中: enter image description here

在这种情况下,如果已经提取了1,2和3,我们只能“提取”块6,如果已经提取了2,3,4,则只提取块7,如果已经提取了3,4,5,则提取块8,块9如果已经提取了6,7,8。

UIPreviewInteraction

从这个直接的先例列表中,我想要一个方法,可以帮助获得大于9个块(1060到100000块之间的实例)的以下“完整的先例列表”。

color=blue;

2 个答案:

答案 0 :(得分:0)

您可以在topological order中迭代块。这是一种可行的方法:

def precedents_transitive(blocks, precedents):
    num_blocks = len(precedents)
    # Mapping between block ids and indices
    mapping = {b: i for i, b in enumerate(blocks)}
    # Direct precedents as sets
    ps = list(map(set, precedents))
    # Transitive precedents as sets, starts with direct precedents
    ps_transitive = list(map(set, precedents))
    # Remaining blocks to visit
    remaining = set(blocks)
    # Visited blocks
    visited = set()
    while remaining:
        # Find a non-visited block such that all its precedents have been visited
        for block in remaining:
            i_block = mapping[block]
            if ps[i_block] <= visited:
                break
        else:
            # If we get here the input was not valid
            raise ValueError('Invalid precedents.')
        # Add transitive precedents of direct predecessors
        ps_transitive[i_block].update(*(ps_transitive[mapping[pred]] for pred in ps[i_block]))
        remaining.remove(block)
        visited.add(block)
    return list(map(sorted, ps_transitive))

以下是您的数据测试:

# List of blocks
blocks = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# List of direct precedents
p = [[] for i in blocks]
p[0] = []
p[1] = []
p[2] = []
p[3] = []
p[4] = []
p[5] = [1, 2, 3]
p[6] = [2, 3, 4]
p[7] = [3, 4, 5]
p[8] = [6, 7, 8]
p_transitive = precedents_transitive(blocks, p)
print(p_transitive)

输出:

[[], [], [], [], [], [1, 2, 3], [2, 3, 4], [3, 4, 5], [1, 2, 3, 4, 5, 6, 7, 8]]

答案 1 :(得分:0)

首先让我们构建一个更有趣的例子:

pit = """
 1  2  3  4  5  6  7  8  9 10 11
   12 13 14 15 16 17 18 19 20
      21 22 23 24 25 26 27
         28 29 30 31 32
            33 34 35
               36
"""

direct_predecessors = {}
row_below = []
for line in pit.strip().split( '\n' )[ ::-1 ]:
    row_current = [ int( x ) for x in line.split() ]
    for i, item in enumerate( row_below ):
        direct_predecessors[ item ] = row_current[ i : i + 3 ]
    row_below = row_current

(注意:与您的问题不同,前导查找键是从零开始的,但值是从一开始的,我选择使用字典,其中值条目可以直接用作键。事实上,如果我没有明确地将它们转换为int(),则块标签可以是任意字符串。如果我们打印内容:

for key, value in sorted( direct_predecessors.items() ):
    print( '%r : %r' % ( key, value ) )

然后我们得到以下输出:

12 : [1, 2, 3]
13 : [2, 3, 4]
14 : [3, 4, 5]
15 : [4, 5, 6]
16 : [5, 6, 7]
17 : [6, 7, 8]
18 : [7, 8, 9]
19 : [8, 9, 10]
20 : [9, 10, 11]
21 : [12, 13, 14]
22 : [13, 14, 15]
23 : [14, 15, 16]
24 : [15, 16, 17]
25 : [16, 17, 18]
26 : [17, 18, 19]
27 : [18, 19, 20]
28 : [21, 22, 23]
29 : [22, 23, 24]
30 : [23, 24, 25]
31 : [24, 25, 26]
32 : [25, 26, 27]
33 : [28, 29, 30]
34 : [29, 30, 31]
35 : [30, 31, 32]
36 : [33, 34, 35]

好的,现在回答你的问题:给定直接前辈,获得所有(直接和间接)前辈。递归方法是一种方法:

def Predecessors( n ):
    result = set( direct_predecessors.get( n, [] ) )
    result |= { indirect for direct in result for indirect in Predecessors( direct ) }
    return result

如果我们尝试一个例子:

print( Predecessors( 31 ) )

输出如下:

set([4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 18, 19, 24, 25, 26])