How to read stdin for 2d python integer array?

I would like to read a 2d array of integers from stdin (or from a file) in Python.

Inoperative code:

from StringIO import StringIO from array import array # fake stdin stdin = StringIO("""1 2 3 4 5 6""") a = array('i') a.fromstring(stdin.read()) 

This gives me an error: a.fromstring (stdin.read ()) ValueError: string length not multiple of element size

+7
source share
3 answers

Several approaches are available to accomplish this. Below are some of the features.

Using array

From the list

Replace the last line of code in the question with the following.

 a.fromlist([int(val) for val in stdin.read().split()]) 

Now:

 >>> a array('i', [1, 2, 3, 4, 5, 6]) 

Con: does not preserve the 2d structure (see comments).

From generator

Note: this option is included in the eryksun comment.

A more efficient way to do this is to use a generator instead of a list. Replace the last two lines of code in the question with:

 a = array('i', (int(val) for row in stdin for val in row.split())) 

This gives the same result as above, but avoids creating an interim list.

Using the NumPy Array

If you want to maintain a 2d structure, you can use a NumPy array. Here is the whole example:

 from StringIO import StringIO import numpy as np # fake stdin stdin = StringIO("""1 2 3 4 5 6""") a = np.loadtxt(stdin, dtype=np.int) 

Now:

 >>> a array([[1, 2], [3, 4], [5, 6]]) 

Using standard lists

It is unclear whether the Python list is suitable. If so, one way to achieve the goal is to replace the last two lines of code in the next question.

 a = [map(int, row.split()) for row in stdin] 

After doing this, we have:

 >>> a [[1, 2], [3, 4], [5, 6]] 
+9
source

I never used array.array, so I had to do something.

The answer to the error message is

ValueError: string length not multiple of element size

How do you determine the size of an element? Well, it depends on the type with which you initialized it. In your case, you initialized it to i, which is a signed int. Now how big is int? Ask your python interpreter ..

 >>> a.itemsize 4 

The above value gives an idea of ​​the problem. Your string is only 11 bytes wide. 11 is not a multiple of 4. But increasing the length of the string will not give you the array {1,2,3,4,5,6} ... I'm not sure what this will give you. Why the uncertainty? Well, read the doctrine below ... (Late, so I highlighted the important role if you are sleepy, like me!)

array.fromfile (f, n) Read n elements ( as machine values ) from the file object f and add them to the end of the array. If fewer than n elements are available, an EOFError will be raised, but the elements that were available are still inserted into the array. f must be a real embedded file object; something else with the read () method will not.

array.fromstring reads data the same way as array.fromfile. Pay attention to bold. "as machine values" means "read as binary." So, to do what you want to do, you need to use the struct module. Check out the code below.

 import struct a = array.array('i') binary_string = struct.pack('iiii', 1, 2, 3, 4) a.fromstring(binary_string) 

The code snippet above loads an array with tlhe values ​​1, 2, 3, 4; as we expect.

Hope this helps.

+2
source
 arr = [] arr = raw_input() 

If you want to split the input with spaces:

 arr = [] arr = raw_input().split() 
-one
source