基于子集列表排序列表(没有嵌套循环)

时间:2018-03-08 11:31:54

标签: python string loops sorting

我正在尝试根据主列表对一长串标签进行排序,并且正在努力有效地实现这一点。如下面的示例所示,我想将长列表中与字符串共用一个开头的所有项目组合在一起,然后按照与“主列表”相同的顺序创建一个新列表。

使用Python我通常会尝试向量化和并行处理数组,但对于基于字符串的数组来说这似乎不太好用。

以下是使用嵌套循环的示例和解决方案:

fruits = ['apple', 'banana', 'orange']  # "master list"
labels = ['banana2', 'apple2', 'orange1', 'banana1', 'apple1', 'apple3']  # "long list"
new_list = []
for fruit in fruits:
    for label in labels:
        if fruit in label:
            new_list.append(label)

print(new_list)然后返回

['apple2', 'apple1', 'apple3', 'banana2', 'banana1', 'orange1']

这可以在没有嵌套循环的情况下完成吗?

为了获得额外的奖励,我理想地希望根据字符串中的最终数字对标签进行排序,例如给出结果:['apple1', 'apple2', 'apple3', 'banana1', 'banana2', 'orange1']

3 个答案:

答案 0 :(得分:2)

这是一种方法,使用list.index派生排序顺序。

fruits = ['apple', 'banana', 'orange']
labels = ['banana2', 'apple2', 'orange1', 'banana1', 'apple1', 'apple3']

res = sorted(labels, key=lambda x: fruits.index(x[:-1]))

# ['apple2', 'apple1', 'apple3', 'banana2', 'banana1', 'orange1']

您也可以使用tuple作为排序键,与一些正则表达式结合使用可以分隔任意大小的整数。

import re

fruits = ['apple', 'banana', 'orange']
labels = ['banana2', 'apple2', 'orange1', 'banana1', 'apple10', 'apple3']

def sorter(mystr, fruits):
    str_split = re.match(r'([a-z]+)([0-9]+)', mystr, re.I).groups()
    return (fruits.index(str_split[0]), int(str_split[1]))

res2 = sorted(labels, key=lambda x: sorter(x, fruits))

# ['apple2', 'apple3', 'apple10', 'banana1', 'banana2', 'orange1']

答案 1 :(得分:1)

另一种简单方法:

import re

fruits = ['apple', 'banana', 'orange']  # "master list"
labels = ['banana2', 'apple2', 'orange1', 'banana1', 'apple10', 'apple3']  # "long list"

def normal_sort(text):
    return [int(c) if c.isdigit() else c for c in re.split('(\d+)', text)]

def func(x):
    x = " ".join(re.findall("[a-zA-Z]+", x))
    return x

print(sorted(sorted(labels, key=func), key=normal_sort))
# ['apple2', 'apple3', 'apple10', 'banana1', 'banana2', 'orange1']

答案 2 :(得分:0)

要改进的几件事情:

  • 您不需要if fruit in label:,您只需使用if fruit == label[0:len(fruit)],因为您不需要完整的子字符串搜索,只需要开头。

  • 您可以先对labels进行排序,这样当您找到第一个时,您可以直接添加,直到检查失败并跳过其余部分,因为这样您就可以确定它们了。不再匹配了。显然排序有成本,但它仍然比每次检查所有内容更有效。您需要一份副本,以免丢失您最初如何排序的参考。