Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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 arg在列表列表中对值进行排序_Python_List_Sorting - Fatal编程技术网

Python arg在列表列表中对值进行排序

Python arg在列表列表中对值进行排序,python,list,sorting,Python,List,Sorting,我有一个列表a,长度m。A的每个列表都包含{1,2,…,n}中的正数。下面是一个示例,其中m=3和n=4 A = [[1, 1, 3], [1, 2], [1, 1, 2, 4]] 我将A中的每个数字x表示为一对(I,j),其中A[I][j]=x。我想将A中的数字按非降序排序;以最低的第一指数打破平局。也就是说,如果A[i1][j1]==A[i2][j2],则(i1,j1)位于(i2,j2)iffi1list.sort 您可以生成索引列表,然后使用键调用list.sort: B = [(i,

我有一个列表
a
,长度
m
A
的每个列表都包含
{1,2,…,n}
中的正数。下面是一个示例,其中
m=3
n=4

A = [[1, 1, 3], [1, 2], [1, 1, 2, 4]]
我将
A
中的每个数字
x
表示为一对
(I,j)
,其中
A[I][j]=x
。我想将
A
中的数字按非降序排序;以最低的第一指数打破平局。也就是说,如果
A[i1][j1]==A[i2][j2]
,则
(i1,j1)
位于
(i2,j2)
iff
i1
list.sort
您可以生成索引列表,然后使用
键调用
list.sort

B = [(i, j) for i, x in enumerate(A) for j, _ in enumerate(x)]
B.sort(key=lambda ix: A[ix[0]][ix[1]])

请注意,在python-2.x上,支持在函数中进行iterable解包,您可以稍微简化
排序
调用:

B.sort(key=lambda (i, j): A[i][j])

已排序
这是上述版本的替代方案,并生成两个列表(一个在内存中,
排序
然后继续工作,以返回另一个副本)


演出 根据大众需求,添加一些时间和情节

从图中,我们可以看到调用
list.sort
sorted
更有效。这是因为
list.sort
执行就地排序,因此创建
sorted
具有的数据副本不会产生时间/空间开销

功能

def cs1(A):
    B = [(i, j) for i, x in enumerate(A) for j, _ in enumerate(x)]
    B.sort(key=lambda ix: A[ix[0]][ix[1]]) 

    return B

def cs2(A):
    return sorted([
           (i, j) for i, x in enumerate(A) for j, _ in enumerate(x)
        ], 
        key=lambda ix: A[ix[0]][ix[1]]
    )

def rorydaulton(A):

    triplets = [(x, i, j) for i, row in enumerate(A) for j, x in enumerate(row)]
    pairs = [(i, j) for x, i, j in sorted(triplets)]

    return pairs

def jpp(A):
    def _create_array(data):
        lens = np.array([len(i) for i in data])
        mask = np.arange(lens.max()) < lens[:,None]
        out = np.full(mask.shape, max(map(max, data))+1, dtype=int)  # Pad with max_value + 1
        out[mask] = np.concatenate(data)
        return out

    def _apply_argsort(arr):
        return np.dstack(np.unravel_index(np.argsort(arr.ravel()), arr.shape))[0]

    return _apply_argsort(_create_array(A))[:sum(map(len, A))]

def agngazer(A):
    idx = np.argsort(np.fromiter(chain(*A), dtype=np.int))
    return np.array(
       tuple((i, j) for i, r in enumerate(A) for j, _ in enumerate(r))
    )[idx]
您可以制作
(x,i,j)
的三元组,对这些三元组进行排序,然后提取索引
(i,j)
。这是因为三元组包含排序所需的所有信息,并按照排序所需的顺序包含在最终列表中。(这被称为“装饰排序不装饰”的习惯用法,与施瓦茨变换有关——帽子尖指向@Morgen,表示名称和概括,以及我解释这项技术的一般性的动机。)这可以组合成一个单独的语句,但为了清楚起见,我在这里将其拆分

A = [[1, 1, 3], [1, 2], [1, 1, 2, 4]]

triplets = [(x, i, j) for i, row in enumerate(A) for j, x in enumerate(row)]
pairs = [(i, j) for x, i, j in sorted(triplets)]
print(pairs)
以下是打印结果:

[(0, 0), (0, 1), (1, 0), (2, 0), (2, 1), (1, 1), (2, 2), (0, 2), (2, 3)]

为了好玩,这里有一个通过第三方库
numpy
的方法。由于昂贵的填充步骤,性能比@coldspeed的解决方案慢约10%

学分:对于这个解决方案,我改编了@Divakar的配方,并逐字复制了@AshwiniChaudhary的解决方案

import numpy as np

A = [[1, 1, 3], [1, 2], [1, 1, 2, 4]]

def create_array(data):

    """Convert jagged list to numpy array; pad with max_value + 1"""

    lens = np.array([len(i) for i in data])
    mask = np.arange(lens.max()) < lens[:,None]
    out = np.full(mask.shape, max(map(max, data))+1, dtype=int)  # Pad with max_value + 1
    out[mask] = np.concatenate(data)
    return out

def apply_argsort(arr):

    """Flatten, argsort, extract indices, then stack into a single array"""

    return np.dstack(np.unravel_index(np.argsort(arr.ravel()), arr.shape))[0]

# limit only to number of elements in A
res = apply_argsort(create_array(A))[:sum(map(len, A))]

print(res)

[[0 0]
 [0 1]
 [1 0]
 [2 0]
 [2 1]
 [1 1]
 [2 2]
 [0 2]
 [2 3]]
将numpy导入为np
A=[[1,1,3],[1,2],[1,1,2,4]]
def创建_阵列(数据):
“”“将锯齿状列表转换为numpy数组;用最大值+1填充”“”
镜头=np.阵列([len(i)表示数据中的i])
mask=np.arange(lens.max())
仅仅因为@jpp玩得很开心:

from itertools import chain
import numpy as np
def agn(A):
    idx = np.argsort(np.fromiter(chain(*A), dtype=np.int))
    return np.array(tuple((i, j) for i, r in enumerate(A) for j, _ in enumerate(r)))[idx]
定时测试: 测试1: 与@coldspeed中的最快方法进行比较:

In [1]: import numpy as np

In [2]: print(np.__version__)
1.13.3

In [3]: from itertools import chain

In [4]: import sys

In [5]: print(sys.version)
3.5.5 |Anaconda, Inc.| (default, Mar 12 2018, 16:25:05) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]

In [6]: A = [[1],[0, 0, 0, 1, 1, 3], [1, 2], [1, 1, 2, 4]] * 10000

In [7]: %timeit np.array(tuple((i, j) for i, r in enumerate(A) for j, _ in enumerate(r)))[np.argsort(np.fromit
   ...: er(chain(*A), dtype=np.int))]
89.4 ms ± 718 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [8]: %timeit B = [(i, j) for i, x in enumerate(A) for j, _ in enumerate(x)]; B.sort(key=lambda ix: A[ix[0]]
   ...: [ix[1]])
93.5 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
测试2a: 此测试使用一个随机生成的大型数组
A
(每个子列表都进行了排序,因为OP列表就是这样显示的):

测试2.b 与测试2.b类似,但使用未排序的数组
A

In [25]: A = [[random.randint(1, 100) for _ in range(random.randint(1,1000))] for _ in range(10000)]

In [26]: %timeit cs1(A)
4.24 s ± 215 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [27]: %timeit agn(A)
3.44 s ± 49.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

这看起来像是一个特殊的例子(也被称为装饰类非装饰),提到它可能会让你的答案更笼统applicable@Morgen:谢谢您添加的信息--我不知道名称或特定转换。如果我正确理解了你的文章,我没有使用转换本身,而是使用了类似的“装饰-排序-不装饰”习惯用法。我第一次想到这个习语是在群论的背景下,而不是在计算机科学中,早在80年代初,我就在解决魔方问题时使用了这个习语。(我对“排序”的理解更为笼统,而不是完全的排序。)说得对。我可能会找到一篇关于装饰类的文章,我主要使用这篇文章,因为它很容易记住是怎么找到的it@coldspeed感谢您的定时测试!我也在我的答案中添加了我自己的测试(与
a
略有不同);这段对话已经结束。
A = [[1, 1, 3], [1, 2], [1, 1, 2, 4]]

triplets = [(x, i, j) for i, row in enumerate(A) for j, x in enumerate(row)]
pairs = [(i, j) for x, i, j in sorted(triplets)]
print(pairs)
[(0, 0), (0, 1), (1, 0), (2, 0), (2, 1), (1, 1), (2, 2), (0, 2), (2, 3)]
import numpy as np

A = [[1, 1, 3], [1, 2], [1, 1, 2, 4]]

def create_array(data):

    """Convert jagged list to numpy array; pad with max_value + 1"""

    lens = np.array([len(i) for i in data])
    mask = np.arange(lens.max()) < lens[:,None]
    out = np.full(mask.shape, max(map(max, data))+1, dtype=int)  # Pad with max_value + 1
    out[mask] = np.concatenate(data)
    return out

def apply_argsort(arr):

    """Flatten, argsort, extract indices, then stack into a single array"""

    return np.dstack(np.unravel_index(np.argsort(arr.ravel()), arr.shape))[0]

# limit only to number of elements in A
res = apply_argsort(create_array(A))[:sum(map(len, A))]

print(res)

[[0 0]
 [0 1]
 [1 0]
 [2 0]
 [2 1]
 [1 1]
 [2 2]
 [0 2]
 [2 3]]
from itertools import chain
import numpy as np
def agn(A):
    idx = np.argsort(np.fromiter(chain(*A), dtype=np.int))
    return np.array(tuple((i, j) for i, r in enumerate(A) for j, _ in enumerate(r)))[idx]
In [1]: import numpy as np

In [2]: print(np.__version__)
1.13.3

In [3]: from itertools import chain

In [4]: import sys

In [5]: print(sys.version)
3.5.5 |Anaconda, Inc.| (default, Mar 12 2018, 16:25:05) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]

In [6]: A = [[1],[0, 0, 0, 1, 1, 3], [1, 2], [1, 1, 2, 4]] * 10000

In [7]: %timeit np.array(tuple((i, j) for i, r in enumerate(A) for j, _ in enumerate(r)))[np.argsort(np.fromit
   ...: er(chain(*A), dtype=np.int))]
89.4 ms ± 718 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [8]: %timeit B = [(i, j) for i, x in enumerate(A) for j, _ in enumerate(x)]; B.sort(key=lambda ix: A[ix[0]]
   ...: [ix[1]])
93.5 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [20]: A = [sorted([random.randint(1, 100) for _ in range(random.randint(1,1000))]) for _ in range(10000)]

In [21]: def agn(A):
    ...:     idx = np.argsort(np.fromiter(chain(*A), dtype=np.int))
    ...:     return np.array(tuple((i, j) for i, r in enumerate(A) for j, _ in enumerate(r)))[idx]
    ...:     

In [22]: %timeit agn(A)
3.1 s ± 62.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [23]: %timeit cs1(A)
3.2 s ± 89.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [25]: A = [[random.randint(1, 100) for _ in range(random.randint(1,1000))] for _ in range(10000)]

In [26]: %timeit cs1(A)
4.24 s ± 215 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [27]: %timeit agn(A)
3.44 s ± 49.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)