2

I have a dynamic array in which I would like to update the userstring, e.g., for a 25 character single string like 'mannysattynastysillyfully'. there would be a 5x5 array .

m a n n y
s a t t y
n a s t y
s i l l y
f u l l y

I have tried multiple things and went through extensive search with bit of information that I got from 1. How to define two-dimensional array in python 2. How to take input in an array + PYTHON? 3.python - how to split an input string into an array?

Am still unable to comprehend how i should be dealing with the user values getting into the dynamic array

Community
  • 1
  • 1
Smple_V
  • 838
  • 3
  • 13
  • 32
  • 3
    what exactly do you mean by `dynamic array` – Thomas Apr 14 '16 at 23:58
  • @Thomas mean the array sizes it self according to the user string, for eg., if the string is 25chr long the array would size as 5x5 – Smple_V Apr 15 '16 at 11:47
  • There really isn't a native multidimensional array in python. There are a few libraries that can do this including pandas and tablib. You could also just use a list of lists, or something like that. – James Robinson Apr 15 '16 at 16:37
  • The real problem is that I am not sure how you are deciding a 25 character string should be a 5x5 array. If it were a 24 character string, would it be 3x8, 8x3, 6x4, etc? Maybe we add an extra space somewhere and force it to 5x5. You would either need a delimiter in your data, or provide the width or count of names. I really can't think of a scenario where someone would enter in names like that though, how are you ending up with 'mannysattynastysillyfully'? – James Robinson Apr 15 '16 at 16:37
  • @JamesRobinson the n in the nxn matrix is odd so whatever the string is it goes straight into that matrix, if there is an extra space at the end it is kept as blank – Smple_V Apr 15 '16 at 19:01

1 Answers1

2

I think this may do what you are after:

>>> def two_dim(inval, width=5):
...     out = []
...     for i in range(0, len(inval) - 1, width):
...         out.append(list(inval[i:i + width]))
...     return out
...
>>> print(two_dim('mannysattynastysillyfully'))
[['m', 'a', 'n', 'n', 'y'], ['s', 'a', 't', 't', 'y'], ['n', 'a', 's', 't', 'y'], ['s', 'i', 'l', 'l', 'y'], ['f', 'u', 'l', 'l', 'y']]

And to print it like you have in the question:

>>> c = two_dim('mannysattynastysillyfully')
>>> for sub in c:
...     print " ".join(sub)
...
m a n n y
s a t t y
n a s t y
s i l l y
f u l l y

NOTE This will only create complete rows, so using a width that is not a factor of the length of the input string will result in lost data. This is easy to change if desired, but I will leave that as an exercise to the reader.

If you are looking to always create a square 2x2, then you could do something like

def is_square(l):
    return math.floor(math.sqrt(l))**2 == l

def two_dim_square(inval):
    if not is_square(len(inval)):
        raise Exception("string length is not a perfect square")
    width = math.sqrt(len(inval))
    # proceed like before with a derived width

EDIT 2

def two_dim(inval, width=5):
    out = []
    for i in range(0, len(inval) - 1, width):
        out.append(list(inval[i:i + width]))
    return out

def print_array(label, inval, joiner=' '):
    print label
    for sub in inval:
        print joiner.join(sub)
    print

print_array("3 by X", two_dim('mannysattynastysillyfully', 3))
print_array("4 by X", two_dim('mannysattynastysillyfully', 4))
print_array("5 by X", two_dim('mannysattynastysillyfully', 5))
print_array("6 by X", two_dim('mannysattynastysillyfully', 6))

Gives the output

3 by X
m a n
n y s
a t t
y n a
s t y
s i l
l y f
u l l

4 by X
m a n n
y s a t
t y n a
s t y s
i l l y
f u l l

5 by X
m a n n y
s a t t y
n a s t y
s i l l y
f u l l y

6 by X
m a n n y s
a t t y n a
s t y s i l
l y f u l l

EDIT 3
If you want all data to always be present, and use a default value for empty cells, then that would look like

def two_dim(inval, width=5, fill=' '):
    out = []
    # This just right-pads the input string with the correct number of fill values so the N*M is complete.
    inval = inval + (fill * (width - (len(inval) % width)))
    for i in range(0, len(inval) - 1, width):
        out.append(list(inval[i:i + width]))
    return out

Called with

print_array("3 by X", two_dim('mannysattynastysillyfully', 3, '*'))

OUTPUT

3 by X
m a n
n y s
a t t
y n a
s t y
s i l
l y f
u l l
y * *
sberry
  • 128,281
  • 18
  • 138
  • 165
  • excellent answer, thanks just a nudge as of what can be done if the width has to be decided on the fly – Smple_V Apr 15 '16 at 12:30
  • What do you mean - "if the width has to be decided on the fly"? – sberry Apr 15 '16 at 13:27
  • i mean if the width of the array is to be decided by the user – Smple_V Apr 15 '16 at 15:23
  • @Smple_V Is there still a question, or do you already understand now? – sberry Apr 15 '16 at 15:42
  • just have to figure out a way to fix the width of the array. Mean like instead of giving it a static number – Smple_V Apr 15 '16 at 16:03
  • The example I showed, `def two_dim(inval, width=5)` has a **default** width of 5, but you can pass in any value you like. `c = two_dim('yourstring', 4)` for example. My note about taking only complete rows still applies though and you would get `[['y', 'o', 'u', 'r'], ['s', 't', 'r', 'i']]` in that case. – sberry Apr 15 '16 at 16:08
  • See my **EDIT 2** above. – sberry Apr 15 '16 at 16:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/109278/discussion-between-smple-v-and-sberry). – Smple_V Apr 15 '16 at 19:29