在Python3中在循环中向列表追加元素(再次)

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

Appending to lists within loops in Python3 (again)

问题

我在逐步向列表中添加元素时遇到了困难。

这是一个最小化工作示例(MWE):

  1. # 给定一个嵌套的值列表或集合
  2. sets = [[1, 2, 3], [1, 2, 4], [1, 2, 5]]
  3. # 将一个值添加到每个子列表,表示该集合在列表中的编号。
  4. n_sets = len(sets)
  5. for s in range(n_sets):
  6. (sets
    展开收缩
    ).insert(0, s)
  7. # 现在重复这些集合reps次
  8. reps = 4
  9. expanded_sets = [item for item in sets for i in range(reps)]
  10. # 然后为每个集合的每次出现分配一个重复编号。
  11. rep_list = list(range(reps)) * n_sets
  12. for i in range(n_sets * reps):
  13. (expanded_sets[i]).insert(0, rep_list[i])
  14. expanded_sets

这段代码返回的结果是:

  1. [[3, 2, 1, 0, 0, 1, 2, 3],
  2. [3, 2, 1, 0, 0, 1, 2, 3],
  3. [3, 2, 1, 0, 0, 1, 2, 3],
  4. [3, 2, 1, 0, 0, 1, 2, 3],
  5. [3, 2, 1, 0, 1, 1, 2, 4],
  6. [3, 2, 1, 0, 1, 1, 2, 4],
  7. [3, 2, 1, 0, 1, 1, 2, 4],
  8. [3, 2, 1, 0, 1, 1, 2, 4],
  9. [3, 2, 1, 0, 2, 1, 2, 5],
  10. [3, 2, 1, 0, 2, 1, 2, 5],
  11. [3, 2, 1, 0, 2, 1, 2, 5],
  12. [3, 2, 1, 0, 2, 1, 2, 5]]

而不是期望的结果:

  1. [[0, 0, 1, 2, 3],
  2. [1, 0, 1, 2, 3],
  3. [2, 0, 1, 2, 3],
  4. [3, 0, 1, 2, 3],
  5. [0, 1, 1, 2, 4],
  6. [1, 1, 1, 2, 4],
  7. [2, 1, 1, 2, 4],
  8. [3, 1, 1, 2, 4],
  9. [0, 2, 1, 2, 5],
  10. [1, 2, 1, 2, 5],
  11. [2, 2, 1, 2, 5],
  12. [3, 2, 1, 2, 5]]

希望这次的回答对你有所帮助。

英文:

I'm having difficulty adding to a list iteratively.

Here's a MWE:

  1. # Given a nested list of values, or sets
  2. sets = [[1, 2, 3], [1, 2, 4], [1, 2, 5]]
  3. # add a value to each sublist giving the number of that set in the list.
  4. n_sets = len(sets)
  5. for s in range(n_sets):
  6. (sets
    展开收缩
    ).insert(0, s)
  7. # Now repeat those sets reps times
  8. reps = 4
  9. expanded_sets = [item for item in sets for i in range(reps)]
  10. # then assign a repetition number to each occurance of a set.
  11. rep_list = list(range(reps)) * n_sets
  12. for i in range(n_sets * reps):
  13. (expanded_sets[i]).insert(0, rep_list[i])
  14. expanded_sets

which returns

  1. [[3, 2, 1, 0, 0, 1, 2, 3],
  2. [3, 2, 1, 0, 0, 1, 2, 3],
  3. [3, 2, 1, 0, 0, 1, 2, 3],
  4. [3, 2, 1, 0, 0, 1, 2, 3],
  5. [3, 2, 1, 0, 1, 1, 2, 4],
  6. [3, 2, 1, 0, 1, 1, 2, 4],
  7. [3, 2, 1, 0, 1, 1, 2, 4],
  8. [3, 2, 1, 0, 1, 1, 2, 4],
  9. [3, 2, 1, 0, 2, 1, 2, 5],
  10. [3, 2, 1, 0, 2, 1, 2, 5],
  11. [3, 2, 1, 0, 2, 1, 2, 5],
  12. [3, 2, 1, 0, 2, 1, 2, 5]]

instead of the desired

  1. [[0, 0, 1, 2, 3],
  2. [1, 0, 1, 2, 3],
  3. [2, 0, 1, 2, 3],
  4. [3, 0, 1, 2, 3],
  5. [0, 1, 1, 2, 4],
  6. [1, 1, 1, 2, 4],
  7. [2, 1, 1, 2, 4],
  8. [3, 1, 1, 2, 4],
  9. [0, 2, 1, 2, 5],
  10. [1, 2, 1, 2, 5],
  11. [2, 2, 1, 2, 5],
  12. [3, 2, 1, 2, 5]]

Just for fun, the first loop returns an expected value of sets

  1. [[0, 1, 2, 3], [1, 1, 2, 4], [2, 1, 2, 5]]

but after the second loop sets changed to

  1. [[3, 2, 1, 0, 0, 1, 2, 3], [3, 2, 1, 0, 1, 1, 2, 4], [3, 2, 1, 0, 2, 1, 2, 5]]

I suspect the issue has something to do with copies and references. I've tried adding .copy() and slices in various places, but with the indexed sublists I haven't come across a combo that works. I'm running Python 3.10.6.

Thanks for looking!

Per suggested solution, [list(range(reps)) for _ in range(n_sets)] doesn't correctly replace the list(range(reps)) * n_sets, since it gives [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]] instead of
the desired [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]. Do I need to flatten, or is there a syntax with the _ notation that gives me a single list?

Further update . . .
replacing

  1. rep_list = list(range(reps)) * n_sets

with

  1. rep_list_nest = [list(range(reps)) for _ in range(n_sets)]
  2. rep_list = [i for sublist in rep_list_nest for i in sublist]

gives the same undesired result for expanded_sets.

答案1

得分: 1

问题出在这里:

  1. expanded_sets = [item
  2. for item in sets
  3. for i in range(reps)]

现在,这个列表中连续包含了sets中的每个元素四次,然后是下一个元素重复四次,以此类推。

创建item的副本可以修复这个问题:

  1. expanded_sets = [item.copy()
  2. for item in sets
  3. for i in range(reps)]

在线尝试

如果你想要一个更符合Python风格的方法,那就认识到结果是两个范围的乘积,并且是你原始的sets列表中所有元素的连接:

  1. from itertools import product
  2. sets = [[1, 2, 3], [1, 2, 4], [1, 2, 5]]
  3. expanded_sets = [[inner_counter, outer_counter] + sets_elem
  4. for sets_elem, outer_counter, inner_counter in product(sets, range(len(sets)), range(4))]

在线尝试

英文:

The problem is here:

  1. expanded_sets = [item
  2. for item in sets
  3. for i in range(reps)]

This list now contains the same element of sets four times in a row, followed by the next element repeated four times, and so on.

Creating copies of item fixes the issue:

  1. expanded_sets = [item.copy()
  2. for item in sets
  3. for i in range(reps)]

Try it online

If you want a more pythonic approach, then recognize that the result is a product of two ranges, and your original sets all concatenated together:

  1. from itertools import product
  2. sets = [[1, 2, 3], [1, 2, 4], [1, 2, 5]]
  3. expanded_sets = [[inner_counter, outer_counter] + sets_elem
  4. for sets_elem, outer_counter, inner_counter in product(sets, range(len(sets)), range(4))]

Try it online

huangapple
  • 本文由 发表于 2023年2月8日 12:28:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75381387.html
匿名

发表评论

匿名网友

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

确定