Python给定旧索引的dict:新索引移动列表中的多个元素

yrefmtwq  于 2023-05-30  发布在  Python
关注(0)|答案(2)|浏览(223)

在Python 3中,如果dict{old index: new index, old index: new index, old index: new index},将多个可能不连续的元素移动到新的可能不连续的索引中的最佳方法是什么

重要提示dict可能不包含元素的所有新位置,这就是为什么第一个例子下面的例子不起作用

编辑:对不起,我忘了提到,你不必担心检查new_idxs中的所有索引是否有效,是否在seq的范围内。new_idxs的键也已经按排序顺序排列

from typing import Any

def move_elements(
    seq: list[Any],
    new_idxs: dict,
) -> list[Any]:
    new = []
    idx = 0
    done = set()
    while len(new) < len(seq):
        if idx in new_idxs and idx not in done:
            new.append(seq[new_idxs[idx]])
            done.add(idx)
        elif idx not in done:
            new.append(seq[idx])
            idx += 1
        else:
            idx += 1
    return new

# works
new_idxs = {0: 1, 1: 0}
seq = [0, 1]
seq = move_elements(seq, new_idxs)
print ("\nexpected:", [1, 0])
print ("actual  :", seq)
# expected output
# [1, 0]

# doesn't work
new_idxs = {3: 0, 5: 1}
seq = [0, 1, 2, 3, 4, 5, 6, 7]
seq = move_elements(seq, new_idxs)
print ("\nexpected:", [3, 5, 0, 1, 2, 4, 6, 7])
print ("actual  :", seq)
# expected output
# [3, 5, 0, 1, 2, 4, 6, 7]

# doesn't work
new_idxs = {3: 6, 5: 7}
seq = [0, 1, 2, 3, 4, 5, 6, 7]
seq = move_elements(seq, new_idxs)
print ("\nexpected:", [0, 1, 2, 4, 6, 7, 3, 5])
print ("actual  :", seq)
# expected output
# [0, 1, 2, 4, 6, 7, 3, 5]

new_idxs = {3: 1, 7: 4}
seq = [0, 1, 2, 3, 4, 5, 6, 7]
seq = move_elements(seq, new_idxs)
print ("\nexpected:", [0, 3, 1, 2, 7, 4, 5, 6])
print ("actual  :", seq)
# expected output
# [0, 3, 1, 2, 7, 4, 5, 6]

new_idxs = {0: 3, 3: 1, 7: 4}
seq = [0, 1, 2, 3, 4, 5, 6, 7]
seq = move_elements(seq, new_idxs)
print ("\nexpected:", [1, 3, 2, 0, 7, 4, 5, 6])
print ("actual  :", seq)
# expected output
# [0, 1, 2, 3, 4, 5, 6, 7]
# [1, 3, 2, 0, 7, 4, 5, 6]
zujrkrfu

zujrkrfu1#

线性时间1我从一个充满虚拟对象的结果列表开始。然后根据请求将元素从输入序列移动到结果列表中。然后用输入序列中剩余的非伪元素替换结果中剩余的伪元素。

from typing import Any

def move_elements(
    seq: list[Any],
    new_idxs: dict,
) -> list[Any]:

    dummy = object()
    res = [dummy] * len(seq)
    seq = seq[:]

    for old, new in new_idxs.items():
        res[new] = seq[old]
        seq[old] = dummy

    remaining = (x for x in seq if x is not dummy)
    for i, x in enumerate(res):
        if x is dummy:
            res[i] = next(remaining)

    return res

def test(seq, new_idxs, expect):
    result = move_elements(seq, new_idxs)
    print('seq:     ', seq)
    print('new_idxs:', new_idxs)
    print('expect:  ', expect)
    print('result:  ', result)
    print('correct? ', result == expect)
    print()

test([0, 1], 
     {0: 1, 1: 0},
     [1, 0])
test([0, 1, 2, 3, 4, 5, 6, 7],
     {3: 0, 5: 1},
     [3, 5, 0, 1, 2, 4, 6, 7])
test([0, 1, 2, 3, 4, 5, 6, 7],
     {3: 6, 5: 7},
     [0, 1, 2, 4, 6, 7, 3, 5])
test([0, 1, 2, 3, 4, 5, 6, 7],
     {3: 1, 7: 4},
     [0, 3, 1, 2, 7, 4, 5, 6])

输出(Attempt This Online!):

seq:      [0, 1]
new_idxs: {0: 1, 1: 0}
expect:   [1, 0]
result:   [1, 0]
correct?  True

seq:      [0, 1, 2, 3, 4, 5, 6, 7]
new_idxs: {3: 0, 5: 1}
expect:   [3, 5, 0, 1, 2, 4, 6, 7]
result:   [3, 5, 0, 1, 2, 4, 6, 7]
correct?  True

seq:      [0, 1, 2, 3, 4, 5, 6, 7]
new_idxs: {3: 6, 5: 7}
expect:   [0, 1, 2, 4, 6, 7, 3, 5]
result:   [0, 1, 2, 4, 6, 7, 3, 5]
correct?  True

seq:      [0, 1, 2, 3, 4, 5, 6, 7]
new_idxs: {3: 1, 7: 4}
expect:   [0, 3, 1, 2, 7, 4, 5, 6]
result:   [0, 3, 1, 2, 7, 4, 5, 6]
correct?  True
cidc1ykv

cidc1ykv2#

解决方案:

def move_elements(
    seq: list,
    new_idxs: dict
) -> list:
    result = [None] * len(seq)
    for old, new in new_idxs.items():
        result[new] = seq[old]
    
    for val in seq:
        res_idx = 0
        while res_idx < len(seq) and result[res_idx] != None:
            res_idx += 1

        if res_idx == len(seq): return result
        
        if val in result: continue
        result[res_idx] = val
               
    return result

输出(针对您的测试用例):

[1, 0]
[3, 5, 0, 1, 2, 4, 6, 7]
[0, 1, 2, 4, 6, 7, 3, 5]
[0, 3, 1, 2, 7, 4, 5, 6]

相关问题