简体   繁体   English

Python:通过双循环填充列表?

[英]Python: filling a list of a list through a double loop?

I am new to Python, and I'm struggling to program a function that fills a matrix.I was attempting to write a sensing function for a robot, yet I noticed something I wasn't quite getting.我是 Python 的新手,我正在努力编写一个填充矩阵的函数。我试图为机器人编写一个传感函数,但我注意到一些我不太明白的东西。 I fill a list of a list iterating it in a loop and checking a condition so as to know which value to assign.我填充一个列表的列表,在循环中对其进行迭代并检查条件,以便知道要分配哪个值。 When I print the current element, the program seems to be giving me what I want, but when I print the entire list of list, it is filled with zeros.当我打印当前元素时,程序似乎给了我想要的东西,但是当我打印整个列表列表时,它用零填充。 How is this possible?这怎么可能? Thanks in advance提前致谢

p=[[0.05,0.05,0.05,0.05, 0.05],[0.05,0.05,0.05,0.05, 0.05],[0.05,0.05,0.05,0.05, 0.05],[0.05,0.05,0.05,0.05, 0.05]]
measurement='G'
sensor_right=0.7
colors = [['R','G','G','R','R'],['R','R','G','R','R'],['R','R','G','G','R'],['R','R','R','R','R']]
sensetable= [ [0.0] * len(p[0]) ]*len(p)
for i in range(len(p)):  
  for j in range(len(p[0])):
    if (colors[i][j]==measurement):
      sensetable[i][j]=1

    else:
      sensetable[i][j]=0


print(sensetable)

UPDATE: Thank you so much for all of your help.更新:非常感谢您的帮助。 This was all part of a function, which takes into account the probabilities stored in p.这是一个函数的一部分,它考虑了存储在 p 中的概率。 I attach the code below.我附上下面的代码。 This was the best way I thought it could be done by reading your replies.这是我认为可以通过阅读您的回复来完成的最佳方式。 I do not see a way of using nested list comprehension in this case, where I do need p[i][j] in my calculations inside the loop.在这种情况下,我没有看到使用嵌套列表理解的方法,我在循环内的计算中确实需要 p[i][j] 。 Please correct me if I am wrong or if you have further suggestions.如果我错了或者您有进一步的建议,请纠正我。 Thank you so much!!非常感谢!!

def sense(p,measurement,sensor_right,colors):
sensetable=[]

for i in range(len(p)):
    aux=[]
    for j in range(len(p[0])):
        aux.append(p[i][j]*sensor_right if colors[i][j]==measurement else p[i][j]*(1-sensor_right))

    sensetable.append(aux)

norm=sum(sum(sensetable,[]))
probTableFin = [[float(j)/norm for j in i] for i in sensetable]

return probTableFin
sensetable = [[int(colors[i][j] == measurement) for j in range(len(p[i]))] for i in range(len(p))]

Breakdown:分解:

colors[i][j] == measurement returns a boolean, int() converts it to 0/1 colors[i][j] == measurement返回一个布尔值, int()将其转换为 0/1

Then it is just basic list comprehension.然后它只是基本的列表理解。 Refer to this for a tutorial :)请参阅此教程:)

And the code和代码

p=[[0.05,0.05,0.05,0.05, 0.05],[0.05,0.05,0.05,0.05, 0.05],[0.05,0.05,0.05,0.05, 0.05],[0.05,0.05,0.05,0.05, 0.05]]
measurement='G'
sensor_right=0.7
colors = [['R','G','G','R','R'],['R','R','G','R','R'],['R','R','G','G','R'],['R','R','R','R','R']]
sensetable = [[int(colors[i][j] == measurement) for j in range(len(p[i]))] for i in range(len(p))]

print (sensetable)

# gives [[0, 1, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 0]]

Explanation to why your code doesn't work解释为什么您的代码不起作用

The problematic line is sensetable = [[0.0] * len(p[0])] * len(p)有问题的行是sensetable = [[0.0] * len(p[0])] * len(p)

Let me simplify it to sensetable = [[0] * 3] * 5 .让我将其简化为sensetable = [[0] * 3] * 5 Works the same, has the same problem, easier to type and explain :)工作相同,有相同的问题,更容易输入和解释:)

So basically in python, a = [0] * 3 creates a list [0, 0, 0].所以基本上在 python 中, a = [0] * 3创建一个列表 [0, 0, 0]。 No problem there.没有问题。

However, problem arises when you call b = [a] * 5 .但是,当您调用b = [a] * 5时会出现问题。 This will create a list [a, a, a, a, a] .这将创建一个列表[a, a, a, a, a] However, each of the a in the list is the same thing .但是,列表中的每个a都是相同的 What this means is they're the same thing , and they share the same memory address ie they're stored at the same place in your memory.这意味着它们是相同的东西,它们共享相同的内存地址,即它们存储在您内存中的相同位置。 Since they're sharing the same memory address, when you change one of them, you'll change all of them.由于它们共享相同的内存地址,因此当您更改其中之一时,您将更改所有这些。 Meaning, if you say b[0][0] = 1 , it'll change a[0] to 1 , and the list will become [[1,0,0],[1,0,0],..] instead of the expected [[1,0,0],[0,0,0],...] .意思是,如果您说b[0][0] = 1 ,它会将a[0]更改为1 ,并且列表将变为[[1,0,0],[1,0,0],..]而不是预期的[[1,0,0],[0,0,0],...]

You can also see this by using the id function.您还可以使用id函数查看此信息。

a = [0] * 3
print (id(a[0]), id(a[1]), id(a[2]))

b = [a] * 5
print (id(b[0]), id(b[1]), id(b[2])) # All `id` are the same!

To fix this, replace b = [a] * 5 with b = [a for _ in range(5)] , or equivalently, b = [[0] * 3 for _ in range(5)] .要解决此问题,请将b = [a] * 5替换为b = [a for _ in range(5)] ,或等效地, b = [[0] * 3 for _ in range(5)] This creates a new copy of a for every b[0], b[1], b[2], b[3], b[4] .这会为每个b[0], b[1], b[2], b[3], b[4]创建一个新的a副本 This makes them all disjoint, and they're not related to each other.这使它们全部脱节,并且它们彼此不相关。

c = [[0] * 3 for _ in range(5)]
print (id(c[0]), id(c[1]), id(c[2])) # Different id

To learn more: List of lists changes reflected across sublists unexpectedly要了解更多信息: 意外反映在子列表中的列表更改列表

Problem问题

The notation sensetable = [[0] * len(p[0])] * len(p) makes in fact a list with one sublist copied X times, so as the last sublist to read contains only zeros you get zeros all at the end.符号sensetable = [[0] * len(p[0])] * len(p)实际上是一个列表,其中一个子列表复制了 X 次,因此,由于要读取的最后一个子列表仅包含零,因此在结尾。

print(sensetable) # [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
sensetable[0][0] = 15
print(sensetable) # [[15, 0, 0, 0, 0], [15, 0, 0, 0, 0], [15, 0, 0, 0, 0], [15, 0, 0, 0, 0]]

Solution解决方案

As you iterate over all the values you don't need to pre-fill a list, just build it when iterating当您遍历所有不需要预先填充列表的值时,只需在迭代时构建它

for i in range(len(p)):
    tmp = []
    for j in range(len(p[0])):
        if colors[i][j] == measurement:
            tmp.append(1)
        else:
            tmp.append(0)
    sensetable.append(tmp)

Improvement改进

  1. Inline the if内联if

     for i in range(len(p)): tmp = [] for j in range(len(p[0])): tmp.append(1 if colors[i][j] == measurement else 0) sensetable.append(tmp)
  2. Improve the append , as int(True)==1, int(False)==0 you can do改进append ,因为int(True)==1, int(False)==0你可以做

    tmp.append(colors[i][j] == measurement)
  3. Use list comprehension once使用列表理解一次

    for i in range(len(p)): sensetable.append([colors[i][j] == measurement for j in range(len(p[0]))])
  4. Use list comprehension twice and no more indice, but directly the items使用列表理解两次,不再使用索引,而是直接使用项目

    sensetable = [[int(letter == measurement) for letter in sublist] for sublist in colors]
sensetable = [[1 if letter==measurement else 0 for letter in color] for color in colors]

You don't need to separately define sensetable !!你不需要单独定义 sensetable !! Code explanation: The above nested list comprehension goes through each element of 'colors' & checks the given condition.代码说明:上面的嵌套列表推导式遍历 'colors' 的每个元素并检查给定的条件。 'color': each list in 'colors', 'letter': each element of each list from colors. 'color':'colors' 中的每个列表,'letter':来自颜色的每个列表的每个元素。 'measurement':'G' '测量':'G'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM