对 python 列表进行排序,同时保持其元素的索引
sort a python list while maintaining its element's indices
我需要对 python 列表进行排序,但排序不应改变元素在排序前的索引。在 php 中有一个名为 asort 的函数可以做到这一点,但是在 python 中如何实现呢?有这样的方法吗?如果没有,如何在更少的行中做到这一点?
例如,举个例子:
$a = [1, 5, 2, 4];
print_r($a);
asort($a);
print_r($a);
输出将是:
Array
(
[0] => 1
[1] => 5
[2] => 2
[3] => 4
)
Array
(
[0] => 1
[2] => 2
[3] => 4
[1] => 5
)
这里 5 在 asort
之后仍然有索引 1 但它已经排到了最后。
我有自己的解决方案,即:将索引创建为整数列表。然后使用 [List Length] 和 [Series] 创建此列表。然后,同步对数值和索引进行排序,即使用相同的排序组件。虽然,这不完全是 asort()
所做的,但非常接近。
有更好的方法吗?那也用更少的行?也许是内置方法?一种有效的方法比更少的行更可取。
谢谢
首先,您将原始值连接到它的索引列表。然后对其进行排序,原始索引将附加到新的排序值。最后解压缩它们以获得两个列表。
i_xs = [(x, i) for (i, x) in enumerate(xs)]
s = sorted(i_xs)
sorted_xs, index_lst = unzip(s)
使用这个
def unzip(ls):
if isinstance(ls, list):
if not ls:
return [], []
else:
xs, ys = zip(*ls)
return list(xs), list(ys)
else:
raise TypeError
例子。在:
[34, 23424, 1212, -2324, 34353]
输出:
[-2324, 34, 1212, 23424, 34353]
[3, 0, 2, 1, 4]
PHP 和 Python 之间的主要区别是 PHP 数组都是关联的和有序的,而在 Python 中你可以有一个 ordered list
or 一个 associative dict
,但不能同时在一个数据结构中。*
* OrderedDict
和 dict
本身开始变得有序,但让我们坚持原语。
所以从根本上说,您需要考虑不同的数据结构。这样做的典型方法是有一个元组列表,一个元组值代表您以前的索引,另一个值是以前的值:
[(0, 'foo'), (1, 'bar'), ...]
您可以使用 enumerate
:
从普通列表中找到它
l = list(enumerate(my_list)) # ['foo', 'bar'] → [(0, 'foo'), (1, 'bar')]
并且可以在过程中排序:
l = sorted(enumerate(my_list), key=lambda i: i[1]) # → [(1, 'bar'), (0, 'foo')]
这里 lambda i: i[1]
只是按第二个元组值排序,即你以前的值。为了简洁起见,您可以将其替换为 operator
模块中的 itemgetter(1)
,或者根据您的排序条件进行必要的调整。
如果你想再次将其转换为关联数据结构,请使用 OrderedDict
:
from collections import OrderedDict
from operator import itemgetter
l = OrderedDict(sorted(enumerate(my_list), key=itemgetter(1)))
我需要对 python 列表进行排序,但排序不应改变元素在排序前的索引。在 php 中有一个名为 asort 的函数可以做到这一点,但是在 python 中如何实现呢?有这样的方法吗?如果没有,如何在更少的行中做到这一点?
例如,举个例子:
$a = [1, 5, 2, 4];
print_r($a);
asort($a);
print_r($a);
输出将是:
Array
(
[0] => 1
[1] => 5
[2] => 2
[3] => 4
)
Array
(
[0] => 1
[2] => 2
[3] => 4
[1] => 5
)
这里 5 在 asort
之后仍然有索引 1 但它已经排到了最后。
我有自己的解决方案,即:将索引创建为整数列表。然后使用 [List Length] 和 [Series] 创建此列表。然后,同步对数值和索引进行排序,即使用相同的排序组件。虽然,这不完全是 asort()
所做的,但非常接近。
有更好的方法吗?那也用更少的行?也许是内置方法?一种有效的方法比更少的行更可取。
谢谢
首先,您将原始值连接到它的索引列表。然后对其进行排序,原始索引将附加到新的排序值。最后解压缩它们以获得两个列表。
i_xs = [(x, i) for (i, x) in enumerate(xs)]
s = sorted(i_xs)
sorted_xs, index_lst = unzip(s)
使用这个
def unzip(ls):
if isinstance(ls, list):
if not ls:
return [], []
else:
xs, ys = zip(*ls)
return list(xs), list(ys)
else:
raise TypeError
例子。在:
[34, 23424, 1212, -2324, 34353]
输出:
[-2324, 34, 1212, 23424, 34353]
[3, 0, 2, 1, 4]
PHP 和 Python 之间的主要区别是 PHP 数组都是关联的和有序的,而在 Python 中你可以有一个 ordered list
or 一个 associative dict
,但不能同时在一个数据结构中。*
* OrderedDict
和 dict
本身开始变得有序,但让我们坚持原语。
所以从根本上说,您需要考虑不同的数据结构。这样做的典型方法是有一个元组列表,一个元组值代表您以前的索引,另一个值是以前的值:
[(0, 'foo'), (1, 'bar'), ...]
您可以使用 enumerate
:
l = list(enumerate(my_list)) # ['foo', 'bar'] → [(0, 'foo'), (1, 'bar')]
并且可以在过程中排序:
l = sorted(enumerate(my_list), key=lambda i: i[1]) # → [(1, 'bar'), (0, 'foo')]
这里 lambda i: i[1]
只是按第二个元组值排序,即你以前的值。为了简洁起见,您可以将其替换为 operator
模块中的 itemgetter(1)
,或者根据您的排序条件进行必要的调整。
如果你想再次将其转换为关联数据结构,请使用 OrderedDict
:
from collections import OrderedDict
from operator import itemgetter
l = OrderedDict(sorted(enumerate(my_list), key=itemgetter(1)))