【问题标题】:Sorting list based on order of substrings in another list根据另一个列表中子字符串的顺序对列表进行排序
【发布时间】:2018-12-27 08:23:43
【问题描述】:

我有两个字符串列表。

list_one = ["c11", "a78", "67b"]
list_two = ["a", "b", "c"]

使用来自list_two 的字符串对list_one 进行排序以获得以下输出的最短方法是什么?

["a78", "67b", "c11"]

编辑 1: 有一个类似的问题Sorting list based on values from another list?,但在那个问题中,他已经有了结果字符串所需索引的列表,而这里我只有子字符串的列表。

编辑 2: 由于上面列表的例子可能不完全具有代表性,我再补充一个案例。

list_one 是 ["1.cde.png", "1.abc.png", "1.bcd.png"] list_two 是["abc", "bcd", "cde"]。 输出应该是[ "1.abc.png", "1.bcd.png", "1.cde.png"]

例如,如果 list_one 比 list_two 短,它应该仍然有效:

list_one 是["1.cde.png", "1.abc.png"] list_two 是["abc", "bcd", "cde"] 输出应该是[ "1.abc.png", "1.cde.png"]

【问题讨论】:

  • 您的预期输出没有意义。为什么67b第二?
  • list_one 和list_two 是什么关系?似乎 list_one 的对象包含 list_two 的值。这是标准吗?
  • @TomWojcik in stackoverflow.com/questions/6618515/… 他已经有了结果字符串所需顺序的列表,而这里我只有子字符串列表
  • @blhsing 因为在 list_two 中,子字符串“b”是第二个

标签: python string list sorting


【解决方案1】:

试试这个

list_one = ["c11", "a78", "67b"]
list_two = ["a", "b", "c"]

[x for y in list_two for x in list_one if y in x]

输出:

["a78", "67b", "c11"]

【讨论】:

    【解决方案2】:
    key = {next((s for s in list_one if v in s), None): i for i, v in enumerate(list_two)}
    print(sorted(list_one, key=key.get))
    

    这个输出:

    ['a78', '67b', 'c11']
    

    【讨论】:

    • 如果 list_one 小于 list_two,您的代码将不起作用。它给出了一个错误“IndexError: list index out of range”
    • 确实如此。然后修复。
    • 为什么是key=key.__getitem__ 而不是key=key.get
    • 我不确定你到底做了什么改变,但它仍然不适用于 list_one 比 list_two 短的情况。例如,我针对 list_one = ["c11", "a78"], list_two = ["a", "b", "c"] 的情况测试了您的代码。输出应该是 ["a78", "c11"]。但它给了我一个错误“IndexError: list index out of range”。
    • @tobias_k 好点。 __getitem__ 完全没有必要。按建议修改。谢谢。
    【解决方案3】:

    假设list_one 中的每个项目都包含list_two 中的一个字符,并且您知道这些字符的类别,例如字母,您可以使用regex 提取这些字母,并构建一个将字符映射到元素的字典。然后,只需查找每个字符的正确元素。

    >>> list_one = ["c11", "a78", "67b"]
    >>> list_two = ["a", "b", "c"]
    >>> d = {re.search("[a-z]", s).group(): s for s in list_one}
    >>> list(map(d.get, list_two))
    ['a78', '67b', 'c11']
    >>> [d[c] for c in list_two]
    ['a78', '67b', 'c11']
    

    除了到目前为止发布的其他方法似乎都是 O(n²),这只是 O(n)。

    当然,该方法可以推广到例如多个字符,或第一个字符串的特定位置的字符,但它总是需要一些模式和关于该模式的知识。例如,对于您最近的示例:

    >>> list_one = ["1.cde.png", "1.abc.png", "1.bcd.png"]
    >>> list_two = ["abc", "cde"]
    >>> d = {re.search("\.(\w+)\.", s).group(1): s for s in list_one}
    >>> d = {s.split(".")[1]: s for s in list_one}  # alternatively without re
    >>> [d[c] for c in list_two if c in d]
    ['1.abc.png', '1.cde.png']
    

    【讨论】:

      【解决方案4】:
      >>> sorted(list_one, key=lambda x: [i for i,e in enumerate(list_two) if e in x][0])
      ['a78', '67b', 'c11']
      

      【讨论】:

        猜你喜欢
        • 2012-08-27
        • 2022-11-16
        • 2018-01-03
        • 1970-01-01
        • 2018-09-15
        • 1970-01-01
        • 1970-01-01
        • 2021-06-25
        • 2023-04-01
        相关资源
        最近更新 更多