0

What I want to do is to take a string(cipher) and devide it to several groups and not to copy them (assume that every 7 characters to one group), All I want to do is take every 7 letters and add them to one row in two dimentional array and the same for the next 7 and so on.

I have tried to do that with two dimentional array and I have some problem that its always change all my arrays for every update, and I dont want to copy it.

Let me give you an example:

def splitter(cipher,key_length):

    rows = math.ceil(len(cipher)/key_length)
    columns = key_length
    arr = [[""]*columns]*rows
    arr1=[]
    for row in range(rows):
        for column in range(columns):
            if (row * columns + column)< len(cipher):
                arr[row][column] = cipher[row * columns + column]
            else:
                arr[row][column] = ""
        arr1.append(arr[row])
    print(arr1)


splitter("QPWKALVRXCQZIKGRBPFAEOMFLJMSDZVDHXCXJYEBIMTRQWNMEAIZRVKCVKVLXNEICFZPZCZZHKMLVZVZIZRRQWDKECHOSNYXXLSPMYKVQXJTDCIOMEEXDQVSRXLRLKZHOV",7)

the result of the print is that its duplicated the least 7 characters for the all array, and I coudnt figure out why this happening, what I'm missing?

the result of this print is:

[['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', ''], ['Z', 'H', 'O', 'V', '', '', '']]
Guy Cohen
  • 194
  • 1
  • 9
  • Possible duplicate of [How to clone or copy a list?](https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list) – Patrick Artner Nov 13 '19 at 21:01
  • Possible duplicate of [List of lists changes reflected across sublists unexpectedly](https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly) – Patrick Artner Nov 13 '19 at 21:02
  • And what you want to do is covered here: [how do you split a list into evenly sized chunks](https://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks) – Patrick Artner Nov 13 '19 at 21:03
  • Yes this is thie one List of lists changes reflected across sublists unexpectedly - https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly – Guy Cohen Nov 13 '19 at 21:15

1 Answers1

1

The problem is this line:

arr = [[""] * columns] * rows

This is a Python "gotcha" - a piece of code which looks on the surface like it should do one thing, but actually does a quite different thing, though the difference is subtle.

What you wanted was a list containing rows different rows. What you actually get is a list containing that many references to the same row. The code [""] * columns only creates one list, so when you fill in the second row's values into that list, it overwrites the first row's values which were previously stored there; then the third row's values overwrite the second row's values, and so on, because they are all references to the same list.

You may find it helpful to visualise the execution step-by-step, to understand what's going on. This link uses the rather excellent Python Tutor tool.


The solution is to create rows different lists explicitly:

arr = [[""] * columns for i in range(rows)]
kaya3
  • 47,440
  • 4
  • 68
  • 97