首页 > 解决方案 > 按规则列表排序一些元素的列表

问题描述

我得到了一个元素列表,比如[C, D, B, A](每个字母都是一个 RGB 颜色的元组)和一个规则列表(第一个元素 > 第二个元素) :,[(D,C), (D,B), (D,A), (C,B), (C,A), (B,A)]所以D必须排在CB并且A(所以排在最后)之后,CBand之后A, (将其放在第 3 位)等。

正确的顺序是[A, B, C, D]

for _ in colors:
    color += [_]
for element in rules:
    listtwo += [(element)]
        
for x in listtwo:
    if x[0] in color:
        color.remove(x[0])
    if x[1] in color:
        color.remove(x[1])

for elements in rules:
    if elements[0] == elements[1]:
        pass
    else:
        listone += [elements]
        for el in listone:
            pos_a = colors.index(el[0])
            pos_b = colors.index(el[1])
            if pos_a > pos_b:
                colors.remove(el[0])
                colors.insert(posizione_b, el[0])

if len(color) > 0:
    colors.remove(colors[0])
colors.reverse()
if len(color) > 0:
    colors.append(colors[0])

它适用于某些特定情况,但不适用于一般情况(并且代码编写得不好)。有任何想法吗?

进一步的例子,它适用于:

colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 255, 255), (255, 255, 0)]

rules = [
    ((0, 0, 255), (255, 0, 0)),
    ((0, 0, 255), (0, 255, 0)),
    ((0, 255, 0), (255, 0, 0)),
    ((255, 255, 0), (0, 0, 255)),
    ((255, 255, 0), (255, 0, 0)),
    ((255, 255, 0), (0, 255, 0)),
    ((0, 255, 255), (0, 0, 255)),
    ((0, 255, 255), (255, 0, 0)),
    ((0, 255, 255), (0, 255, 0)),
    ((255, 255, 0), (0, 255, 255))
]

输出是:

[(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 255, 255), (255, 255, 0)]

它不适用于此示例:

colors = [
    (142, 150, 92), (133, 228, 115), (149, 198, 219), (250, 150, 227),
    (79, 247, 87), (197, 223, 252), (104, 132, 238), (121, 154, 210),
    (127, 219, 167), (222, 190, 134), (191, 52, 233)
]

rules = [
    ((79, 247, 87), (250, 150, 227)),
    ((250, 150, 227), (149, 198, 219)),
    ((79, 247, 87), (149, 198, 219)),
    ((79, 247, 87), (133, 228, 115)),
    ((149, 198, 219), (133, 228, 115)),
    ((133, 228, 115), (142, 150, 92)),
    ((250, 150, 227), (142, 150, 92)),
    ((79, 247, 87), (142, 150, 92)),
    ((197, 223, 252), (142, 150, 92)),
    ((197, 223, 252), (250, 150, 227)),
    ((121, 154, 210), (79, 247, 87)),
    ((121, 154, 210), (197, 223, 252)),
    ((121, 154, 210), (142, 150, 92)),
    ((127, 219, 167), (121, 154, 210)),
    ((197, 223, 252), (79, 247, 87)),
    ((127, 219, 167), (79, 247, 87)),
    ((127, 219, 167), (142, 150, 92)),
    ((121, 154, 210), (104, 132, 238)),
    ((104, 132, 238), (197, 223, 252)),
    ((127, 219, 167), (197, 223, 252)),
    ((222, 190, 134), (121, 154, 210)),
    ((191, 52, 233), (121, 154, 210)),
    ((222, 190, 134), (191, 52, 233)),
    ((191, 52, 233), (127, 219, 167)),
    ((191, 52, 233), (222, 190, 134))

]

错误的输出:

[(142, 150, 92), (133, 228, 115), (149, 198, 219), (250, 150, 227),
 (79, 247, 87), (197, 223, 252), (104, 132, 238), (121, 154, 210),
 (127, 219, 167), (222, 190, 134), (191, 52, 233)]

正确的输出:

[(142, 150, 92), (133, 228, 115), (149, 198, 219), (250, 150, 227),
 (79, 247, 87), (197, 223, 252), (104, 132, 238), (121, 154, 210),
 (127, 219, 167), (191, 52, 233), (222, 190, 134)]

标签: pythonpython-3.x

解决方案


您可以使用graphlib.TopologicalSorterPython 3.9 中引入的:

ts = TopologicalSorter()
for color in colors:
    ts.add(color)
for rule in rules:
    ts.add(*rule)
ordered = list(ts.static_order())

但是,根据您的规则,这会导致错误

graphlib.CycleError: ('nodes are in a cycle', [(191, 52, 233), (222, 190, 134), (191, 52, 233)])

这也是Martijn指出的。

但是,如果您删除不正确的规则,那么它会给您预期的结果。

演示:

from graphlib import TopologicalSorter

colors = [(142, 150, 92), (133, 228, 115), (149, 198, 219), (250, 150, 227), (79, 247, 87), (197, 223, 252), (104, 132, 238), (121, 154, 210), (127, 219, 167), (222, 190, 134), (191, 52, 233)]
rules = [((79, 247, 87), (250, 150, 227)), ((250, 150, 227), (149, 198, 219)), ((79, 247, 87), (149, 198, 219)), ((79, 247, 87), (133, 228, 115)), ((149, 198, 219), (133, 228, 115)), ((133, 228, 115), (142, 150, 92)), ((250, 150, 227), (142, 150, 92)), ((79, 247, 87), (142, 150, 92)), ((197, 223, 252), (142, 150, 92)), ((197, 223, 252), (250, 150, 227)), ((121, 154, 210), (79, 247, 87)), ((121, 154, 210), (197, 223, 252)), ((121, 154, 210), (142, 150, 92)), ((127, 219, 167), (121, 154, 210)), ((197, 223, 252), (79, 247, 87)), ((127, 219, 167), (79, 247, 87)), ((127, 219, 167), (142, 150, 92)), ((121, 154, 210), (104, 132, 238)), ((104, 132, 238), (197, 223, 252)), ((127, 219, 167), (197, 223, 252)), ((222, 190, 134), (121, 154, 210)), ((191, 52, 233), (121, 154, 210)), ((222, 190, 134), (191, 52, 233)), ((191, 52, 233), (127, 219, 167)), ((191, 52, 233), (222, 190, 134))]
expect = [(142, 150, 92), (133, 228, 115), (149, 198, 219), (250, 150, 227), (79, 247, 87), (197, 223, 252), (104, 132, 238), (121, 154, 210), (127, 219, 167), (191, 52, 233), (222, 190, 134)]

rules.remove(((191, 52, 233), (222, 190, 134)))

ts = TopologicalSorter()
for color in colors:
    ts.add(color)
for rule in rules:
    ts.add(*rule)
ordered = list(ts.static_order())

print(ordered)
print(ordered == expect)

输出:

[(142, 150, 92), (133, 228, 115), (149, 198, 219), (250, 150, 227), (79, 247, 87), (197, 223, 252), (104, 132, 238), (121, 154, 210), (127, 219, 167), (191, 52, 233), (222, 190, 134)]
True

推荐阅读