Python:基于列表不完整序列查找单词/字符串的底层序列

Python:基于列表不完整序列查找单词/字符串的底层序列,python,Python,假设以下列表包含字符串(不一定是字母): 列表中的每一项都表示分类数据,其基本顺序类似于字母表中的字母。每个字符串都有一个前导项和一个后继项(第一个和最后一个除外),正如您所看到的,一些项目['a','b','d','f']几乎完成了。例如,此特定项不包含字母e。项目['b','d','e','f']包含字母e(大概顺序正确),但不包含字母a。这些项一起确实包含有关字符串的基本序列的信息,但没有一个单独的项可以提供此信息。我应该提到的是,这些信只是一个例子。否则,排序将很容易 我希望获得基于对齐

假设以下列表包含字符串(不一定是字母):

列表中的每一项都表示分类数据,其基本顺序类似于字母表中的字母。每个字符串都有一个前导项和一个后继项(第一个和最后一个除外),正如您所看到的,一些项目
['a','b','d','f']
几乎完成了。例如,此特定项不包含字母
e
。项目
['b','d','e','f']
包含字母
e
(大概顺序正确),但不包含字母
a
。这些项一起确实包含有关字符串的基本序列的信息,但没有一个单独的项可以提供此信息。我应该提到的是,这些信只是一个例子。否则,排序将很容易

我希望获得基于对齐的唯一排序项(这些列表意义上的对齐。如下所示:

['a', 'b', 'd', 'e', 'f']
我相信这是一个以前已经解决过的常见问题,但我很难找到类似的案例。处理类似的问题,但基本事实是已知的。这里我想找到字符串的基本顺序

不幸的是,最长的序列不能保证以例如“a”开头

我看过difflib,但我不确定这是否是正确的工具箱。任何提示都非常感谢

编辑:

我找到了一个基于NetworkX的解决方案

import networkx as nx

l = [['b', 'd'], ['b', 'd', 'e', 'f'], ['a', 'b', 'd', 'f'], ['b', 'd', 'e'], ['d', 'e', 'f'], ['f'], ['d', 'f']]

# get tuples (start, stop)
new_l = []
for item in l:
    for index, subitem in enumerate(item):
        if len(item) > 1:
            if index < len(item)-1:
                new_l.append((subitem, item[index+1]))
# create a graph using those tuples
uo_graph = nx.DiGraph()
for item in new_l:
    uo_graph.add_edge(*item)


[item for item in nx.topological_sort(uo_graph)]

Out[10]: ['a', 'b', 'd', 'e', 'f']
将networkx导入为nx
l=['b','d'],['b','d','e','f'],['a','b','d','f'],['b','d','e'],['d','e','f'],['f'],['d','f']]
#获取元组(开始、停止)
新的
对于l中的项目:
对于索引,枚举中的子项(项):
如果长度(项目)>1:
如果索引

如果这类问题有更多的pythonic解决方案,那将很有趣。特别是,如果有多个解决方案,知道如何应用检查将很有趣。

好的,我只是无法停止思考这个问题,现在我终于找到了我要找的解决方案。这只有在你的问题确实存在的情况下才有效定义明确,意味着a)数据集中没有矛盾,b)只有一个顺序可以从中派生,没有歧义的余地

x = [['b', 'd'], ['b', 'd', 'e', 'f], ['a', 'b', 'd', 'f], ['b', 'd', 'e'], [['d', 'e', 'f'], ['f'], ['d', 'f']]
for l in x:
    l.sort()
#if you want all the elements inside in order...elements should be of the same type
q = set()
for l in x:
    q.update(l)
s = list(q)
s.sort()
基于这一假设,我注意到您的问题看起来非常类似于。我知道这种类型的谜语,但我花了很长时间才弄明白它到底叫什么

起初,我以为你可以通过解一个线性方程组来解决这类问题,但很快我意识到这并不是那么简单。然后我搜索了可以解决这类问题的Python库。令我惊讶的是,似乎根本不存在。最后我遇到了一个问题,有人问如何用Python解决爱因斯坦的谜语,评论中有人指出了Raymond Hettinger的一篇演讲,内容是关于如何使用Python解决定义明确的问题。有趣的是当他开始谈论。到他幻灯片的相关部分。这些解决方案正是您解决问题所需要的。我们非常幸运的是,他让所有这些信息都变得如此容易获取(以下是答案),因为否则,我可能无法找到一个适合您的问题的解决方案

出于某种原因,文档中缺少了一个关键部分,那就是他提出的。他们很难找到,在某个时候,我甚至想给他发个短信,问问在哪里可以找到他们。幸运的是,这没有必要,因为最终,我找到了它们

有了所有的工具,我只需要根据您的问题修改解算器。最困难的部分是提出/转换规则,确定如何从数据集中检索订单。实际上只有一条规则,那就是连续规则,有点像这样:

对于数据集中的任何连续项对,按照顺序,第二项只能放置在第一项之后的位置。它们之间可以有其他项目,但不一定要有

要使实现正确,需要经过相当多的尝试和错误

最后,这里是我的SAT解算器版本,它可以解决您的问题:

import numpy as np
import itertools
from pprint import pprint
from sys import intern

from sat_utils import solve_one, from_dnf, one_of


datasets = [
    ['b', 'd'], ['b', 'd', 'e', 'f'], ['a', 'b', 'd', 'f'], ['b', 'd', 'e'],
    ['d', 'e', 'f'], ['f'], ['d', 'f']
]

values = set(itertools.chain.from_iterable(datasets))
positions = np.arange(len(values))
order = np.empty(positions.size, dtype=object)


def comb(value, position):
    """Format how a value is shown at a given position"""
    return intern(f'{value} {position}')


def found_at(value, position):
    """Value known to be at a specific position"""
    return [(comb(value, position),)]


def consecutive(value1, value2):
    """
    The values are in consecutive positions:  a & b | a & _ & b |
    a & _ & _ & b ...

    """
    lst = [
        (comb(value1, i), comb(value2, j+i+1)) for i in range(len(positions))
        for j in range(len(positions[i+1:]))
    ]
    return from_dnf(lst)


cnf = []

# each value gets assigned to exactly one position
for value in values:
    cnf += one_of(comb(value, position) for position in positions)

# for each consecutive value pair, add all potential successions
for subset in datasets:
    for value1, value2 in zip(subset, subset[1:]):
        cnf += consecutive(value1, value2)


solution = solve_one(cnf)
for pair in solution:
    value, position = pair.split()
    order[int(position)] = value
pprint(order)  # array(['a', 'b', 'd', 'e', 'f'], dtype=object)
我相信这仍然可以在这里和那里进行优化,我知道代码比您的解决方案长得多,但我认为从技术角度来看,使用SAT解算器是一种非常好的方法。如果你相信Raymond Hettinger在他的演讲中所说的话,这也是相当快的,而且规模非常好

请确保彻底测试,因为我不能保证我没有犯任何错误


作为旁注:为了确定样本数据集的唯一项,我使用了评论中指出的技巧。

你所说的“对齐”是什么意思?请详细解释算法!如果你的意思是你可能应该这么说,因为我们不是所有人都是生物学家。试着把它说得更清楚。如果你投票赞成重新开始这个问题,那就太好了。谢谢你的反馈。我试图澄清。不幸的是,这是一个糟糕的例子。字符串不一定是字母。哇。我喜欢这些答案,它们确实让我看到了一些我以前从未见过的东西。谢谢你
import numpy as np
import itertools
from pprint import pprint
from sys import intern

from sat_utils import solve_one, from_dnf, one_of


datasets = [
    ['b', 'd'], ['b', 'd', 'e', 'f'], ['a', 'b', 'd', 'f'], ['b', 'd', 'e'],
    ['d', 'e', 'f'], ['f'], ['d', 'f']
]

values = set(itertools.chain.from_iterable(datasets))
positions = np.arange(len(values))
order = np.empty(positions.size, dtype=object)


def comb(value, position):
    """Format how a value is shown at a given position"""
    return intern(f'{value} {position}')


def found_at(value, position):
    """Value known to be at a specific position"""
    return [(comb(value, position),)]


def consecutive(value1, value2):
    """
    The values are in consecutive positions:  a & b | a & _ & b |
    a & _ & _ & b ...

    """
    lst = [
        (comb(value1, i), comb(value2, j+i+1)) for i in range(len(positions))
        for j in range(len(positions[i+1:]))
    ]
    return from_dnf(lst)


cnf = []

# each value gets assigned to exactly one position
for value in values:
    cnf += one_of(comb(value, position) for position in positions)

# for each consecutive value pair, add all potential successions
for subset in datasets:
    for value1, value2 in zip(subset, subset[1:]):
        cnf += consecutive(value1, value2)


solution = solve_one(cnf)
for pair in solution:
    value, position = pair.split()
    order[int(position)] = value
pprint(order)  # array(['a', 'b', 'd', 'e', 'f'], dtype=object)