Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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_List_Sorting - Fatal编程技术网

在Python中组合两个排序列表

在Python中组合两个排序列表,python,list,sorting,Python,List,Sorting,我有两个对象列表。每个列表都已按datetime类型的对象属性排序。我想把这两个列表合并成一个排序列表。排序是最好的方法还是Python中有更智能的方法?这只是合并。将每个列表视为一个堆栈,并连续弹出两个堆栈头中较小的一个,将该项添加到结果列表中,直到其中一个堆栈为空。然后将所有剩余的项目添加到结果列表中。好吧,简单的方法(将两个列表合并成一个大列表并排序)将是O(N*log(N))复杂度。另一方面,如果手动实现合并(我不知道pythonlibs中是否有现成的代码,但我不是专家),复杂性将是O(

我有两个对象列表。每个列表都已按datetime类型的对象属性排序。我想把这两个列表合并成一个排序列表。排序是最好的方法还是Python中有更智能的方法?

这只是合并。将每个列表视为一个堆栈,并连续弹出两个堆栈头中较小的一个,将该项添加到结果列表中,直到其中一个堆栈为空。然后将所有剩余的项目添加到结果列表中。

好吧,简单的方法(将两个列表合并成一个大列表并排序)将是O(N*log(N))复杂度。另一方面,如果手动实现合并(我不知道pythonlibs中是否有现成的代码,但我不是专家),复杂性将是O(N),这显然更快。 巴里·凯利(Barry Kelly)在文章中很好地描述了这个想法。

def compareDate(obj1,obj2):
def compareDate(obj1, obj2):
    if obj1.getDate() < obj2.getDate():
        return -1
    elif obj1.getDate() > obj2.getDate():
        return 1
    else:
        return 0



list = list1 + list2
list.sort(compareDate)
如果obj1.getDate()obj2.getDate(): 返回1 其他: 返回0 列表=列表1+列表2 列表.排序(比较)
将对列表进行适当排序。为比较两个对象定义自己的函数,并将该函数传递到内置的排序函数中


不要使用冒泡排序,它的性能很差。

使用合并排序的“合并”步骤,它在O(n)时间内运行

从(伪代码):


这是两个排序列表的简单合并。看看下面的示例代码,它合并了两个已排序的整数列表

#!/usr/bin/env python
## merge.py -- Merge two sorted lists -*- Python -*-
## Time-stamp: "2009-01-21 14:02:57 ghoseb"

l1 = [1, 3, 4, 7]
l2 = [0, 2, 5, 6, 8, 9]

def merge_sorted_lists(l1, l2):
    """Merge sort two sorted lists

    Arguments:
    - `l1`: First sorted list
    - `l2`: Second sorted list
    """
    sorted_list = []

    # Copy both the args to make sure the original lists are not
    # modified
    l1 = l1[:]
    l2 = l2[:]

    while (l1 and l2):
        if (l1[0] <= l2[0]): # Compare both heads
            item = l1.pop(0) # Pop from the head
            sorted_list.append(item)
        else:
            item = l2.pop(0)
            sorted_list.append(item)

    # Add the remaining of the lists
    sorted_list.extend(l1 if l1 else l2)

    return sorted_list

if __name__ == '__main__':
    print merge_sorted_lists(l1, l2)
#/usr/bin/env python
##merge.py--合并两个排序列表-*-Python-*-
##时间戳:“2009-01-2114:02:57 ghoseb”
l1=[1,3,4,7]
l2=[0,2,5,6,8,9]
def合并排序列表(l1、l2):
“”“合并排序两个已排序的列表
论据:
-`l1`:第一个排序的列表
-`l2`:第二个排序列表
"""
已排序的_列表=[]
#复制两个参数以确保原始列表不存在
#修改
l1=l1[:]
l2=l2[:]
而(l1和l2):

如果(l1[0]人们似乎过于复杂化了。只需将这两个列表合并,然后对它们进行排序:

>>> l1 = [1, 3, 4, 7]
>>> l2 = [0, 2, 5, 6, 8, 9]
>>> l1.extend(l2)
>>> sorted(l1)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
..或更短(且无需修改
l1
):

…简单!另外,它只使用两个内置函数,因此假设列表的大小合理,它应该比在循环中实现排序/合并更快。更重要的是,上面的代码要少得多,可读性也很强

如果您的列表很大(我猜超过几十万),使用替代/自定义排序方法可能会更快,但可能会先进行其他优化(例如,不存储数百万个
datetime
对象)

使用
timeit.Timer().repeat()
(它将函数重复1000000次),我粗略地对照解决方案对其进行了基准测试,并且
排序(l1+l2)
大大加快了速度:

merge\u sorted\u list
take

[9.7439379692077637, 9.8844599723815918, 9.552299976348877]
[2.860386848449707, 2.7589840888977051, 2.7682540416717529]
sorted(l1+l2)
take

[9.7439379692077637, 9.8844599723815918, 9.552299976348877]
[2.860386848449707, 2.7589840888977051, 2.7682540416717529]
解决方案中有一个轻微的缺陷,使其为O(n**2),而不是O(n)。
问题在于,这正在执行:

item = l1.pop(0)
对于链表或deques,这将是一个O(1)操作,因此不会影响复杂性,但由于python列表是作为向量实现的,因此它将l1的其余元素复制到左一个空格,即O(n)操作。由于每次通过列表都会执行此操作,因此它将O(n)算法转换为O(n**2)这可以通过使用一种不改变源列表,只跟踪当前位置的方法来纠正

我已经尝试过将一个修正的算法与一个简单的排序(l1+l2)进行基准测试,正如

对于不同大小的列表,我得到以下计时(重复100次):

因此,事实上,看起来dbr是正确的,除非您希望得到非常大的列表,否则最好只使用sorted(),尽管它的算法复杂度更差。收支平衡点是每个源列表中大约有100万项(总共200万项)

不过,合并方法的一个优点是,作为生成器重写非常简单,它将使用更少的内存(不需要中间列表)

[编辑] 我在一个更接近问题的情况下重试了这个问题——使用一个包含字段“
date
”的对象列表,该字段是一个datetime对象。 将上述算法更改为与
.date
进行比较,并将排序方法更改为:

return sorted(l1 + l2, key=operator.attrgetter('date'))
这确实改变了一些事情。比较更昂贵意味着相对于实现的恒定时间速度,我们执行的数字变得更重要。这意味着merge弥补了损失,取代sort()方法的是100000项。比较基于更复杂的对象(比如大字符串或列表)可能会进一步改变这种平衡

# items:  1000   10000 100000  1000000[1]
merge  :  0.161  2.034 23.370  253.68
sort   :  0.111  1.523 25.223  313.20
[1] :注意:事实上,我只对1000000个项目重复了10次,并相应地放大,因为速度相当慢

在Python中有没有更聪明的方法来实现这一点

这一点还没有提到,所以我将继续——python 2.6+的heapq模块中有一个。如果您希望做的只是完成一些事情,这可能是一个更好的主意。当然,如果您想实现自己的,合并排序的合并是一个不错的选择

>>> list1 = [1, 5, 8, 10, 50]
>>> list2 = [3, 4, 29, 41, 45, 49]
>>> from heapq import merge
>>> list(merge(list1, list2))
[1, 3, 4, 5, 8, 10, 29, 41, 45, 49, 50]
给你

输出:

2008-12-05 02:00:00
2008-12-31 23:00:00
2009-01-01 13:00:00
2009-01-02 12:00:00
2009-01-03 05:00:00
2009-01-04 15:00:00

我打赌这比任何花哨的纯Python合并算法都要快,即使对于大数据也是如此。Python 2.6的
heapq.merge
完全是另一回事。

长话短说,除非
len(l1+l2)~1000000
使用:

L = l1 + l2
L.sort()

可以找到图的说明和源代码

该图形由以下命令生成:

$ python make-figures.py --nsublists 2 --maxn=0x100000 -s merge_funcs.merge_26 -s merge_funcs.sort_builtin

递归实现低于。平均性能为O(n)

def merge_sorted_list(A、B、sorted_list=None):
如果已排序\u列表==无:
已排序的_列表=[]
切片索引=0
对于A中的元素:
if元素Python的
from datetime import datetime
from itertools import chain
from operator import attrgetter

class DT:
    def __init__(self, dt):
        self.dt = dt

list1 = [DT(datetime(2008, 12, 5, 2)),
         DT(datetime(2009, 1, 1, 13)),
         DT(datetime(2009, 1, 3, 5))]

list2 = [DT(datetime(2008, 12, 31, 23)),
         DT(datetime(2009, 1, 2, 12)),
         DT(datetime(2009, 1, 4, 15))]

list3 = sorted(chain(list1, list2), key=attrgetter('dt'))
for item in list3:
    print item.dt
2008-12-05 02:00:00
2008-12-31 23:00:00
2009-01-01 13:00:00
2009-01-02 12:00:00
2009-01-03 05:00:00
2009-01-04 15:00:00
L = l1 + l2
L.sort()
$ python make-figures.py --nsublists 2 --maxn=0x100000 -s merge_funcs.merge_26 -s merge_funcs.sort_builtin
def merge_sorted_lists(A, B, sorted_list = None):
    if sorted_list == None:
        sorted_list = []

    slice_index = 0
    for element in A:
        if element <= B[0]:
            sorted_list.append(element)
            slice_index += 1
        else:
            return merge_sorted_lists(B, A[slice_index:], sorted_list)

    return sorted_list + B
def merge_sorted_lists_as_generator(A, B):
    slice_index = 0
    for element in A:
        if element <= B[0]:
            slice_index += 1
            yield element       
        else:
            for sorted_element in merge_sorted_lists_as_generator(B, A[slice_index:]):
                yield sorted_element
            return        

    for element in B:
        yield element
def merge_arrays(a, b):
    l= []

    while len(a) > 0 and len(b)>0:
        if a[0] < b[0]: l.append(a.pop(0))    
        else:l.append(b.pop(0))

    l.extend(a+b)
    print( l )
import random

    n=int(input("Enter size of table 1")); #size of list 1
    m=int(input("Enter size of table 2")); # size of list 2
    tb1=[random.randrange(1,101,1) for _ in range(n)] # filling the list with random
    tb2=[random.randrange(1,101,1) for _ in range(m)] # numbers between 1 and 100
    tb1.sort(); #sort the list 1 
    tb2.sort(); # sort the list 2
    fus=[]; # creat an empty list
    print(tb1); # print the list 1
    print('------------------------------------');
    print(tb2); # print the list 2
    print('------------------------------------');
    i=0;j=0;  # varialbles to cross the list
    while(i<n and j<m):
        if(tb1[i]<tb2[j]):
            fus.append(tb1[i]); 
            i+=1;
        else:
            fus.append(tb2[j]);
            j+=1;

    if(i<n):
        fus+=tb1[i:n];
    if(j<m):
        fus+=tb2[j:m];

    print(fus);

  # this code is used to merge two sorted lists in one sorted list (FUS) without
  #sorting the (FUS)
def merge(lst1,lst2):
    len1=len(lst1)
    len2=len(lst2)
    i,j=0,0
    while(i<len1 and j<len2):
        if(lst1[i]<lst2[j]):
                yield lst1[i]
                i+=1
        else:
                yield lst2[j]
                j+=1
    if(i==len1):
        while(j<len2):
                yield lst2[j]
                j+=1
    elif(j==len2):
        while(i<len1):
                yield lst1[i]
                i+=1
l1=[1,3,5,7]
l2=[2,4,6,8,9]
mergelst=(val for val in merge(l1,l2))
print(*mergelst)
def merge_sort(a,b):

    pa = 0
    pb = 0
    result = []

    while pa < len(a) and pb < len(b):
        if a[pa] <= b[pb]:
            result.append(a[pa])
            pa += 1
        else:
            result.append(b[pb])
            pb += 1

    remained = a[pa:] + b[pb:]
    result.extend(remained)


return result
def merge_lists(L1, L2):
    """
    L1, L2: sorted lists of numbers, one of them could be empty.

    returns a merged and sorted list of L1 and L2.
    """

    # When one of them is an empty list, returns the other list
    if not L1:
        return L2
    elif not L2:
        return L1

    result = []
    i = 0
    j = 0

    for k in range(len(L1) + len(L2)):
        if L1[i] <= L2[j]:
            result.append(L1[i])
            if i < len(L1) - 1:
                i += 1
            else:
                result += L2[j:]  # When the last element in L1 is reached,
                break             # append the rest of L2 to result.
        else:
            result.append(L2[j])
            if j < len(L2) - 1:
                j += 1
            else:
                result += L1[i:]  # When the last element in L2 is reached,
                break             # append the rest of L1 to result.

    return result

L1 = [1, 3, 5]
L2 = [2, 4, 6, 8]
merge_lists(L1, L2)               # Should return [1, 2, 3, 4, 5, 6, 8]
merge_lists([], L1)               # Should return [1, 3, 5]
def merge(l1, l2):
  m, m2 = len(l1), len(l2)
  newList = []
  l, r = 0, 0
  while l < m and r < m2:
    if l1[l] < l2[r]:
      newList.append(l1[l])
      l += 1
    else:
      newList.append(l2[r])
      r += 1
  return newList + l1[l:] + l2[r:]
def merge_sorted_lists(listA,listB,func):
    merged = list()
    iA = 0
    iB = 0
    while True:
        hasA = iA < len(listA)
        hasB = iB < len(listB)
        if not hasA and not hasB:
            break
        valA = None if not hasA else listA[iA]
        valB = None if not hasB else listB[iB]
        a = None if not hasA else func(valA)
        b = None if not hasB else func(valB)
        if (not hasB or a<b) and hasA:
            merged.append(valA)
            iA += 1
        elif hasB:
            merged.append(valB)
            iB += 1
    return merged
def merge_sorted_list(nums1: list, nums2:list) -> list:
        m = len(nums1)
        n = len(nums2)
        
        nums1 = nums1.copy()
        nums2 = nums2.copy()
        nums1.extend([0 for i in range(n)])
        while m > 0 and n > 0:
            if nums1[m-1] >= nums2[n-1]:
                nums1[m+n-1] = nums1[m-1]
                m -= 1
            else:
                nums1[m+n-1] = nums2[n-1]
                n -= 1
        if n > 0:
            nums1[:n] = nums2[:n]
        return nums1

l1 = [1, 3, 4, 7]    
l2 =  [0, 2, 5, 6, 8, 9]    
print(merge_sorted_list(l1, l2))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
def in_built_sort(list1, list2):
    // time complexity : O(nlog n) 
    return sorted(list1 + list2)
def custom_sort(list1, list2):
    // time complexity : O(n)
    merged_list_size = len(list1) + len(list2)
    merged_list = [None] * merged_list_size

    current_index_list1 = 0
    current_index_list2 = 0
    current_index_merged = 0
    while current_index_merged < merged_list_size:
        if (not current_index_list1 >= len(list1) and (current_index_list2 >= len(list2) or list1[current_index_list1] < list2[current_index_list2])):
            merged_list[current_index_merged] = list1[current_index_list1]
            current_index_list1 += 1
        else:
            merged_list[current_index_merged] = list2[current_index_list2]
            current_index_list2 += 1

        current_index_merged += 1
    return merged_list
print(timeit.timeit(stmt=in_built_sort, number=10))  // 250.44088469999997  O(nlog n)   
print(timeit.timeit(stmt=custom_sort, number=10)) // 125.82338159999999  O(n)