Pythonic风格的单步通过两个列表和避免idx?

2024-06-16 11:39:04 发布

您现在位置:Python中文网/ 问答频道 /正文

(在我开始之前,让我们先假设这是一个面试问题,我的目的是避免仅仅打电话。)

我有一个可以工作的Python代码:

def merge_sorted_lists(left, right):
    leftlen = len(left)
    rightlen = len(right)
    leftidx = 0
    rightidx = 0
    newlist = []
    while leftidx < leftlen or rightidx < rightlen:
        if rightidx == rightlen or left[leftidx] <= right[rightidx]:
            newlist.append(left[leftidx])
            leftidx += 1
        elif leftidx == leftlen or right[rightidx] < left[leftidx]:
            newlist.append(right[rightidx])
            rightidx += 1
    return newlist
我是一个长时间的C++程序员,最近学习了足够多的Python,知道这个“气味”非常丰富,使用了IDX。当迭代器的发展需要这种微调控制时,有没有更优雅的方法来遍历两个列表?你知道吗


Tags: or代码目的rightlendefmergeleft
3条回答

呃,首先,我想先用发电机来代替。我使用yield而不是构建一个列表,因为a)生成器可以是无限的,b)嘿,一旦你开始使用生成器,不妨一直使用生成器。你知道吗

def merge(left,right): 
    left = iter(left)
    right = iter(right)
    left_val = next(left)
    right_val = next(right)
    try:
        while True:
            if left_val <= right_val:
                yield left_val
                left_val = next(left) #left.next() in python2
            else:
                yield right_val
                right_val = next(right)
    except StopIteration: #I have exhausted one of the iterators
        if left_val <= right_val:
            #left list depleted
            yield right_val
            for i in right: yield i #or use yield from right, if your python is fancy enough
        else:
            #right list depleted
            yield left_val
            for i in left: yield i 
In [2]: f = merge([0,4,17],[2,4,5,6,6,6])
In [3]: list(f)
Out[3]: [0, 2, 4, 4, 5, 6, 6, 6, 17]

我可能会为此创建一个合并生成器:

def merge_generator(llist, rlist):
    while len(llist) + len(rlist) > 0:
        if len(llist) == 0:
            yield rlist[0]
            rlist = [1:]
        elif len(rlist) == 0:
            yield llist[0]
            llist = [1:]
        else:
            if llist[0] < rlist[0]:
                yield rlist[0]
                rlist = rlist[1:]
            else:
                yield llist[0]
                llist = llist[1:]

不过,这只是一个骨架,你可能会把它做得更好,例如,通过分离环等

我知道您希望避免使用“排序”是因为您需要一个更好地描述算法的解决方案,但我真诚地认为pythonic解决方案需要它。你知道吗

def merge_sorted_lists(left,right):
    return sorted(left+right)

对于公开合理算法而不跟踪索引的非pythonic解决方案,可以尝试以下递归解决方案:

def merge_sorted_lists(left,right,acc=[]):
    if not left:
        return acc + right
    if not right:
        return acc + left
    if left[0] < right[0]:
        return merge_sorted_lists(left[1:],right,acc=acc+[left[0]])
    else:
        return merge_sorted_lists(left,right[1:],acc=acc+[right[0]])

这一个比我的另一个解决方案长很多行,长输入可能会淹没堆栈。你知道吗

相关问题 更多 >