0

I have a string str = "abcd"

I want to replace the 1st char of str with "X", append to empty list, replace the 2nd char with "X", append to list, repeat until all elements have been replaced, resulting in the following list of lists:

[['N', 'b', 'c', 'd'],
 ['a', 'N', 'c', 'd'],
 ['a', 'b', 'N', 'd'],
 ['a', 'b', 'c', 'N']]

I've tried:

str = "abcd"
bla = list(str)
blabla = [bla]*len(bla)
for i,e in enumerate(blabla):
    e[i]="N"

I didnt "append" because I dont know how to in this situation. The unwanted result is:

[['N', 'N', 'N', 'N'],
 ['N', 'N', 'N', 'N'],
 ['N', 'N', 'N', 'N'],
 ['N', 'N', 'N', 'N']]

What is the best solution in python 3.5?

am313
  • 1
  • 1

5 Answers5

1

The following line will create multiple references to same object instead of independent lists, which is why changing one of them will affect the others.

blabla = [bla]*len(bla)

Also don't use python built-in type names and keywords as your argument names.

You don't need to create an empty list before appending your items. Instead you can just use enumerate within a nested list comprehension:

In [42]: [['N' if ind==i else char for ind, char in enumerate(st)] for i in range(len(st))]
Out[42]: 
[['N', 'b', 'c', 'd'],
 ['a', 'N', 'c', 'd'],
 ['a', 'b', 'N', 'd'],
 ['a', 'b', 'c', 'N']]
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • Using keywords as argument names? Is that actually possible? – Stefan Pochmann Mar 21 '17 at 20:55
  • @StefanPochmann Yes it's not possible to use them exactly the way they are, but in different cases like FALSE. It doesn't have an affection like using built-in type names that copies them but will make a confusion and in not pythonic in terms of coding style. – Mazdak Mar 21 '17 at 21:50
0

As others point out, your problem is here: blabla = [bla]*len(bla)

blabla points to list bla 4 times. Changes to either element in blabla will change all elements.

If you want to continue with your method, define the list as blabla = [list(bla) for _ in bla]. Otherwise other answers are valid.

busybear
  • 10,194
  • 1
  • 25
  • 42
0
s = 'abcd'

res = []
for i in range(len(s)):
    l = list(s) 
    l[i] = 'N'
    res.append(l)

print res
DevLounge
  • 8,313
  • 3
  • 31
  • 44
0
string = "abcd"

ret = []
for l in range(len(string)):
    t = list(string)
    t[l] = 'X'
    ret.append(t)

print(ret)  # [['X', 'b', 'c', 'd'], ['a', 'X', 'c', 'd'], ['a', 'b', 'X', 'd'], ['a', 'b', 'c', 'X']]
Oleksii Filonenko
  • 1,551
  • 1
  • 17
  • 27
0
mystr = "abcd"
bla = list(mystr)
old_d =  [bla]* 4

# As others pointed, old_d is list of list of same objects. You can see the memory address of each element

print("memory address for old_d's elements are {}, {}, {}, {}".format(id(old_d[0]), id(old_d[1]),id(old_d[2]),id(old_d[3])))

#call list function as many times as lenfth of the string using list comprehension. 

new_d =  [list(mystr) for i in list(mystr)]    
print("memory address for new_d's elements are {}, {}, {}, {}".format(id(new_d[0]), id(new_d[1]),id(new_d[2]),id(new_d[3])))

for i,_ in enumerate(bla):
    new_d[i][i] = "N"

print new_d

results in:

memory address for old_d's elements is 66070248, 66070248, 66070248, 66070248
memory address for new_d's elements are 135819952, 135819912, 135819872, 135819752
[['N', 'b', 'c', 'd'], ['a', 'N', 'c', 'd'], ['a', 'b', 'N', 'd'], ['a', 'b', 'c', 'N']]
plasmon360
  • 4,109
  • 1
  • 16
  • 19