检查列表是否按自定义顺序
Check if a list is in a custom order
我正在尝试验证列表说:
X = ['a','c', 'c', 'b', 'd','d','d']
针对自定义排序列表:
Y = ['a',b','d']
在这种情况下,X 针对 Y 验证应该 return True
而不管其中的额外元素和重复项,只要它符合 Y
中的顺序并且至少包含两个元素。
案例:
X = ['a','b'] # Returns True
X = ['d','a', 'a', 'c','b'] # Returns False
X = ['c','a','b', 'b', 'c'] # Returns True
我现在最多只能删除重复项和多余元素。我没有尝试使用自定义列表对它们进行排序。我只需要验证订单。我所做的或至少尝试过的是创建一个字典,其中的值是订单的索引。谁能指出我正确的方向?
从 X 创建一个新列表,其中仅包含 Y 中没有重复的元素。然后,类似地,从 Y 中删除 X 中不包含的所有元素并进行重复数据删除。那么你的检查只是一个简单的相等性检查。
def deduplicate(iterable):
seen = set()
return [seen.add(x) or x for x in iterable if x not in seen]
def goes_with_order(X, Y):
Xs = set(X); Ys = set(Y)
X = deduplicate(x for x in X if x in Ys)
Y = deduplicate(y for y in Y if y in Xs)
return X == Y
from itertools import zip_longest, groupby
okay = list(x == y for y, (x, _) in zip_longest(
(y for y in Y if y in X), groupby(x for x in X if x in Y)))
print(len(okay) >= 2 and all(okay))
首先我们从两个列表中丢弃不必要的元素。然后我们可以使用 groupby
折叠 X
相同元素的序列。例如,您的第一个示例 ['a', 'c', 'c', 'b', 'd', 'd', 'd']
首先变为 ['a', 'c', 'c', 'b'] (by discarding the unnecessary
'd'), then
[('a', _), ('c', _), ( 'b', _)]。如果我们逐个元素地比较它的键与 Y
没有不必要的位,并且至少有 2 个,我们有一个匹配项。如果顺序被违反了(比如['b', 'c', 'c', 'a', 'd', 'd', 'd']
,本来okay
里面有一个False
,就会失败,如果某处多出一个元素,就会和[=进行比较20=](多亏了 zip_longest
),False
又会出现在 okay
.
这可以通过使用集来加速成员查找来改进。
我正在尝试验证列表说:
X = ['a','c', 'c', 'b', 'd','d','d']
针对自定义排序列表:
Y = ['a',b','d']
在这种情况下,X 针对 Y 验证应该 return True
而不管其中的额外元素和重复项,只要它符合 Y
中的顺序并且至少包含两个元素。
案例:
X = ['a','b'] # Returns True
X = ['d','a', 'a', 'c','b'] # Returns False
X = ['c','a','b', 'b', 'c'] # Returns True
我现在最多只能删除重复项和多余元素。我没有尝试使用自定义列表对它们进行排序。我只需要验证订单。我所做的或至少尝试过的是创建一个字典,其中的值是订单的索引。谁能指出我正确的方向?
从 X 创建一个新列表,其中仅包含 Y 中没有重复的元素。然后,类似地,从 Y 中删除 X 中不包含的所有元素并进行重复数据删除。那么你的检查只是一个简单的相等性检查。
def deduplicate(iterable):
seen = set()
return [seen.add(x) or x for x in iterable if x not in seen]
def goes_with_order(X, Y):
Xs = set(X); Ys = set(Y)
X = deduplicate(x for x in X if x in Ys)
Y = deduplicate(y for y in Y if y in Xs)
return X == Y
from itertools import zip_longest, groupby
okay = list(x == y for y, (x, _) in zip_longest(
(y for y in Y if y in X), groupby(x for x in X if x in Y)))
print(len(okay) >= 2 and all(okay))
首先我们从两个列表中丢弃不必要的元素。然后我们可以使用 groupby
折叠 X
相同元素的序列。例如,您的第一个示例 ['a', 'c', 'c', 'b', 'd', 'd', 'd']
首先变为 ['a', 'c', 'c', 'b'] (by discarding the unnecessary
'd'), then
[('a', _), ('c', _), ( 'b', _)]。如果我们逐个元素地比较它的键与 Y
没有不必要的位,并且至少有 2 个,我们有一个匹配项。如果顺序被违反了(比如['b', 'c', 'c', 'a', 'd', 'd', 'd']
,本来okay
里面有一个False
,就会失败,如果某处多出一个元素,就会和[=进行比较20=](多亏了 zip_longest
),False
又会出现在 okay
.
这可以通过使用集来加速成员查找来改进。