如何基于python中的直接前置列表获得完整的前置列表?
我的问题与露天矿中矿石块的开采有关。如下文所述,这些区块具有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]如何基于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]=[]
您可以在中迭代块。以下是一种可能的方法:
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])