如何基于python中的直接前置列表获得完整的前置列表?

如何基于python中的直接前置列表获得完整的前置列表?,python,python-3.x,python-2.7,Python,Python 3.x,Python 2.7,我的问题与露天矿中矿石块的开采有关。如下文所述,这些区块具有pecedência关系。 在此表示中,我们有6个块,其中: 在这种情况下,如果已经提取了1、2和3,我们只能“提取”块6;如果已经提取了2、3、4,我们只能“提取”块7;如果已经提取了3、4、5,我们只能“提取”块8;如果已经提取了6、7、8,我们只能“提取”块9 导入系统 区块=[1,2,3,4,5,6,7,8,9]#区块列表 p=[[]表示块中的i]#直接先例列表 p[0]=[] p[1]=[] p[2]=[] p[3]=[]

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

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

导入系统 区块=[1,2,3,4,5,6,7,8,9]#区块列表 p=[[]表示块中的i]#直接先例列表 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] 从这个直接的先例列表中,我想要一个方法,可以帮助获得大于9个块(介于1060和100000个块之间)的实例的以下“完整先例列表”

导入系统 区块=[1,2,3,4,5,6,7,8,9]#区块列表 p=[[]对于块中的i]#完整的先例列表 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]=[1,2,3,4,5,6,7,8]
您可以在中迭代块。以下是一种可能的方法:

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))
输出:

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

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

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])

你保证总是有一个“充满”三角形?如果不是,输入数组如何与部分填充的三角形相关联?也许可以尝试构建一个树状结构,但每个子级有多个父级?所以问题不是计算初始先例列表,对吗?在这种情况下,这将是一个输入?是的,我已经有了初始先例列表。Patrik,这是p问题。理论上,它应该是优先关系的三角化,但实际上不是。但是jdehesa方法对于任何类型的区块排列都非常有效。非常感谢你的提问。
set([4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 18, 19, 24, 25, 26])