Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何根据另一个列表的值对列表进行排序?_Python_Python 3.x_Sorting - Fatal编程技术网

Python 如何根据另一个列表的值对列表进行排序?

Python 如何根据另一个列表的值对列表进行排序?,python,python-3.x,sorting,Python,Python 3.x,Sorting,我的两份清单是: lst_1 = [[1, 'John'], [2, 'Mcquin'], [4, 'Paul'], [7, 'Jimmy'], [9, 'Coco'], [11, 'Coco']] lst_2 = [[3, 'Mcquin', 1], [6, 'Paul', 6], [5, 'John', 15], [12, 'Coco', 18], [8, 'Jimmy', 24], [10, 'Coco', 24]] 根据lst_2(lst_2[i][1])子列表中的第二个值对lst_1

我的两份清单是:

lst_1 = [[1, 'John'], [2, 'Mcquin'], [4, 'Paul'], [7, 'Jimmy'], [9, 'Coco'], [11, 'Coco']]
lst_2 = [[3, 'Mcquin', 1], [6, 'Paul', 6], [5, 'John', 15], [12, 'Coco', 18], [8, 'Jimmy', 24], [10, 'Coco', 24]]
根据
lst_2
lst_2[i][1]
)子列表中的第二个值对
lst_1
进行排序的最有效方法是什么? 首选输出:

[[2, 'Mcquin'], [4, 'Paul'], [1, 'John'], [9, 'Coco'], [7, 'Jimmy'], [11, 'Coco']]
如果有相同名称的重复项(本例中为Coco),则无所谓。此外,列表将始终包含与此处相同的名称。

给定两个列表:

xs = [[4, 'a'], [3, 'b'], [7, 'c'], [10, 'd']]
ys = [ 7, 3, 4, 10]
下一行按照
ys
中项目的顺序对列表
xs
进行排序:

[x for y in ys for x in xs if x[0] == y]
结果:

>>> [x for y in ys for x in xs if x[0] == y]
[[7, 'c'], [3, 'b'], [4, 'a'], [10, 'd']]

虽然不是pythonish,但仍然易于理解和使用:

lst_new = []
for item in lst_2:
    name = item[1]
    for item2 in lst_1:
        if name == item2[1]:
            lst_new.append(list.copy(item2))
            lst_1.remove(item2)
            #item2[1] = "" is also an option but it's worse for long inputs
            break
输出:

>>> lst_new
[[2, 'Mcquin'], [4, 'Paul'], [1, 'John'], [9, 'Coco'], [7, 'Jimmy'], [11, 'Coco']]
试试这个:

l = sorted(lst_1, key=lambda x: [i[2] for i in lst_2 if i[1] == x[1]][0])
说明:仅当第二个值与参数(i[1]==x[1])匹配时,我们才使用lst_2中的第三个值(i[2])作为键进行排序


请注意,如果lst_2中缺少lst_1中存在的值,则会导致错误(可能是合理的,因为缺少键)。

如果两个列表的名称数量相同,则可以将每个元素的索引存储在中,然后在排序过程中找到某个项时,弹出每个索引并将其用作排序键

演示:

from collections import defaultdict, deque

lst_1 = [[1, 'John'], [2, 'Mcquin'], [4, 'Paul'], [7, 'Jimmy'], [9, 'Coco'], [11, 'Coco']]
lst_2 = [[3, 'Mcquin', 1], [6, 'Paul', 6], [5, 'John', 15], [12, 'Coco', 18], [8, 'Jimmy', 24], [10, 'Coco', 24]]

sort_map = defaultdict(deque)
for i, x in enumerate(lst_2):
    sort_map[x[1]].append(i)

result = sorted(lst_1, key=lambda x: sort_map[x[1]].popleft())

print(result)
[[2, 'Mcquin'], [4, 'Paul'], [1, 'John'], [9, 'Coco'], [7, 'Jimmy'], [11, 'Coco']]. 
输出:

from collections import defaultdict, deque

lst_1 = [[1, 'John'], [2, 'Mcquin'], [4, 'Paul'], [7, 'Jimmy'], [9, 'Coco'], [11, 'Coco']]
lst_2 = [[3, 'Mcquin', 1], [6, 'Paul', 6], [5, 'John', 15], [12, 'Coco', 18], [8, 'Jimmy', 24], [10, 'Coco', 24]]

sort_map = defaultdict(deque)
for i, x in enumerate(lst_2):
    sort_map[x[1]].append(i)

result = sorted(lst_1, key=lambda x: sort_map[x[1]].popleft())

print(result)
[[2, 'Mcquin'], [4, 'Paul'], [1, 'John'], [9, 'Coco'], [7, 'Jimmy'], [11, 'Coco']]. 
注意:您可以使用以固定时间从一开始弹出元素,如上所示。这一微小的改进允许上述解决方案保持总体O(NlogN),这是排序的成本

编辑:我想我有一个
O(n)
解决方案


最初,我认为我们可以创建一个
字典,根据
lst_2
将名称和索引显示在最终列表中。然后我们可以通过排序
lst_1
来创建最终列表-给出
O(n log(n))
解决方案

但是,该方法的问题是,
lst_2
中存在重复的名称!而且,这种新方法甚至具有更好的时间复杂度


首先,我们根据
lst_1
创建一个字典,其中每个
键都是一个名称,每个值都是对应于该名称的数字列表(感谢RoadRunner)

通过使用
deque
,我们保持
lst_1
中具有相同名称的元素的顺序。此外,我们还可以在
O(1)
时间内对
deque
调用
.popleft

然后,这允许我们在
lst_2
上迭代(不需要任何排序,因为它已经按顺序排列了),并将名称和我们创建的字典中的第一个值项附加到一个新列表中

如果我们使用
.popleft()
获取第一个元素,我们也会删除它,这意味着当该名称在
lst_2
中出现时,我们会在
lst_1
中获取下一个值

下面是代码:

import collections
vals = {}
for v, n in lst_1:
    vals.setdefault(n, collections.deque()).append(v)

#vals == {'Paul': [4], 'Coco': [9, 11], 'John': [1], 'Mcquin': [2], 'Jimmy': [7]}
#        (each key here ^^ is actually a deque but it's easier to see with lists)
r = []
for _,n,_ in lst_2:
    r.append([n, vals[n].popleft()])
给出
r
(结果)如下:


lst_1
的条目如何映射到
lst_2
,您首选的输出不是基于
lst_2[i][1]
,而是基于此?它是按照第二个列表中每个名字第一次出现的顺序按逻辑排列的:
[2,'Mcquin']
'Paul'
提供的(
lst_2[1][1]
)-你想象了什么样的排序方式?@lilisten例如,如果
lst_2[0][1]='Mcquin'
,那么新排序的
lst_1[0]
应该是包含
'Mcquin'
的子列表。请编辑您的问题,使排序顺序尽可能具体。解释下一票,因为这符合操作意图。我看到下一票的唯一原因是这是
O(nm)
。除此之外,这是一个完全有效的解决方案。我认为这是一个非常有创意的解决方案。啊,我没有想到
项[2]=”
。不错@RoadRunner是的,这不是很有效,但如果列表不会很长,我看不出有理由写一个更复杂的algorithm@JohnSmith实际上,您可以简单地执行删除(项目2)
并使算法更快地处理较长的列表最后三个条目应该是
[12,'Coco',18],[8,'Jimmy',24],[10,'Coco',24]
@JohnSmith查看更新后的答案,它现在可以正常工作(为之前的错误感到抱歉),而且效率更高!
pop(0)
我相信是O(N)。如果您使用
popleft()
from
deque
这将是一个O(N)解决方案,因为它是O(1)相反,当从前面弹出时。干得好:-)。@RoadRunner非常有趣,让我读了很多关于CPython实现的
列表
!我现在更新了使用
deque
的答案。