【问题标题】:Sublists of a list sorted by two different keys按两个不同键排序的列表的子列表
【发布时间】:2016-05-07 09:14:28
【问题描述】:

我有一个算法遇到以下情况;我想知道是否有可能进行一些改进(我认为不可能,但我可能错了)。

我有一个L 的对象列表。我有两个不同的(且独立的)键用于对它们进行排序:mykey1mykey2。实际上,我可以在算法开始时以两种方式对列表进行排序,而无需花费大量成本;因此,我有两个列表:

A = sorted(L, key=mykey1)
B = sorted(L, key=mykey2)

(Python 语法,但我认为任何人都可以理解)。只要复杂度保持在 O(n log n) 以下,我就可以在这个阶段完美地做更多的事情(初始化新变量)。

我需要提取A许多个子列表;出于显而易见的原因,我想在算法的主循环中使用索引(开始和结束),而不是实际复制子列表。

现在,对于A 的任意子列表(由两个索引已知),是否有一些棘手的方法可以根据B 中的相应顺序(相同对象的)迭代其对象?

这是一个快速而肮脏的例子:

L = [(7,2), (4,3), (5,9), (1,8)]
mykey1 = lambda e: e[0]
mykey2 = lambda e: e[1]
A = sorted(L, key=mykey1) # A = [(1,8), (4,3), (5,9), (7,2)]
B = sorted(L, key=mykey2) # B = [(7,2), (4,3), (1,8), (5,9)]

在处理由A[0:2](即[(1,8), (4,3)])组成的子列表时,是否有一些棘手的方法来迭代[(4,3), (1,8)](因为根据键mykey2,对象(4,3) 位于对象(1,8) 之前. 为了达到这个目的,我想避免迭代除实际属于 A[0:2] 的对象之外的任何其他对象?

我可以通过遍历整个 B 并检查对象是否在子列表中(通过向对象在A) 中给出其位置;我能做得更好吗?

【问题讨论】:

    标签: algorithm sorting iteration sublist


    【解决方案1】:
    I would suggest the next code snippet:
    
        L = [(7,2), (4,3), (5,9), (1,8)]
        mykey1 = lambda e: e[0]
        mykey2 = lambda e: e[1]
        A = sorted(L, key=mykey1)
        C = [sorted(_, key=mykey2) for _ in (A[0:_] for _ in (_ for _ in range(1, len(A) + 1)))]
    
    C will be a list containing the sub-lists:
    [[(1, 8)],
     [(4, 3), (1, 8)],
     [(4, 3), (1, 8), (5, 9)],
     [(7, 2), (4, 3), (1, 8), (5, 9)]]
    
    Or, if we want to make C a [generator][1] (instead of a list); for lists we are keeping all elements in memory (performance issue) :
    
        C = (sorted(_, key=mykey2) for _ in (A[0:_] for _ in (_ for _ in range(1, len(A) + 1))))
    
    Hope it helps.
    

    【讨论】:

    • 这假设他只对从 A 中的第一项开始的 A 的子列表感兴趣。
    【解决方案2】:

    我已经很久没有使用 Python 了,但是这样的东西不会有用吗?

    C = sorted(A[0:2], key=mykey2)
    

    然后在将此“B”排序/键应用于 A 子列表以生成它之后迭代 C,或者您可以改为减去列表

    C = B - A[2:2]
    

    如果您的子列表可以增量生成,这可能是一种生成它们的简单方法,已经按 B 排序顺序。与其从 A 子列表开始并尝试以 B 顺序遍历它们,不如反过来从 B 开始并通过按 A 顺序取出项目来生成子列表。

    或者我在这里错过了什么。这个答案似乎太简单了。

    【讨论】:

    • 嗯,我想你会引入 O(n log n) 复杂度(尽管我必须检查它,因为你排序的列表较小);我认为 O(n) 解决方案(迭代 B 并检查它是否属于子列表)会更好。我宁愿在进入算法之前预先计算尽可能多的东西。
    • 您如何选择子列表?诀窍可能在于该操作。如果您可以从 B 开始并提取 A[4],则 A[0:3] 将按 B 顺序排序。如果你更进一步,你可以通过取出你不想要的部分来逐步生成你的子列表。只是另一个想法。
    • 我必须考虑一下;它可能确实有帮助。我需要一点时间来弄清楚。
    • 这是我唯一能想到的利用您已经按照您想要 A 子列表的顺序拥有 B 的事实。扭转问题,以便您生成以 B 开头的子列表并按 A 顺序取出项目,而不是从 A 开始生成子列表,然后尝试按 B 顺序迭代/排序它们。
    猜你喜欢
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多