Python给定旧索引和新索引的字典,在列表中移动多个元素。

huangapple go评论59阅读模式
英文:

Python given dict of old index: new index move multiple elements in a list

问题

以下是您要翻译的代码部分:

In Python 3 what would be the best way to move multiple potentially non-contiguous elements to new potentially non-contiguous indexes given a `dict` of `{old index: new index, old index: new index, old index: new index}`

**Important Note**: the `dict` may not contain all the new positions of elements, this is why the examples below the first example do not work

Edit: Sorry I forgot to mention that you don't have to worry about checking all the indexes in `new_idxs` are valid and within the bounds of `seq`. The keys of `new_idxs` are also already in sorted order

```python
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]
英文:

In Python 3 what would be the best way to move multiple potentially non-contiguous elements to new potentially non-contiguous indexes given a dict of {old index: new index, old index: new index, old index: new index}

Important Note: the dict may not contain all the new positions of elements, this is why the examples below the first example do not work

Edit: Sorry I forgot to mention that you don't have to worry about checking all the indexes in new_idxs are valid and within the bounds of seq. The keys of new_idxs are also already in sorted order

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]

答案1

得分: 1

这是您提供的Python代码的中文翻译:

# 一个线性时间复杂度的算法。首先创建一个由虚拟对象填充的结果列表。然后按请求将输入序列中的元素移动到结果列表中。然后用输入序列中剩余的非虚拟元素替换结果中的剩余虚拟元素。

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])

输出结果:

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
英文:

A linear time one. I start with a result list full of dummy objects. Then move elements from the input sequence into the result list as requested. Then replace the remaining dummies in the result with the remaining non-dummy elements from the input sequence.

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])

Output (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

答案2

得分: 0

以下是您要翻译的代码部分:

# 一个解决方案:
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]
英文:

A solution:

def move_elements(
seq: list,
new_idxs: dict
) -&gt; 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 &lt; 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

Output (for your test cases):

[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]

huangapple
  • 本文由 发表于 2023年5月26日 01:14:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76334787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定