Как читать стандартный ввод в массив двухмерных чисел python? - PullRequest
8 голосов
/ 19 ноября 2011

Я хотел бы прочитать двумерный массив целых чисел из стандартного ввода (или из файла) в Python.

нерабочий код:

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())

Это дает мне ошибку: a.fromstring (stdin.read ()) ValueError: длина строки не кратна размеру элемента

Ответы [ 3 ]

12 голосов
/ 19 ноября 2011

Существует несколько подходов для достижения этой цели.Ниже приведены несколько возможностей.

Использование array

Из списка

Заменить последнюю строку кода в вопросе следующим:

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

Сейчас:

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

Con: не сохраняет 2D-структуру (см. Комментарии).

От генератора

Примечание: этоопция включена из комментариев eryksun.

Более эффективный способ сделать это - использовать генератор вместо списка.Замените последние две строки кода в вопросе на:

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

Это приводит к тому же результату, что и опция выше, но избегает создания промежуточного списка.

Использование массива NumPy

Если вы хотите сохранить 2d структуру, вы можете использовать массив NumPy.Вот весь пример:

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)

Сейчас:

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

Использование стандартных списков

Из вопроса не ясно, приемлем ли список Python.Если это так, один из способов достижения цели - заменить две последние строки кода в вопросе следующим:

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

После выполнения этого у нас будет:

>>> a
[[1, 2], [3, 4], [5, 6]]
2 голосов
/ 19 ноября 2011

Я никогда не использовал array.array, поэтому мне пришлось немного покопаться.

Ответ есть в сообщении об ошибке -

ValueError: длина строки некратный размеру предмета

Как определить размер предмета?Ну, это зависит от типа, с которым вы его инициализировали.В вашем случае вы инициализировали его с i , который является int со знаком.Теперь, насколько большой Int?Спросите своего интерпретатора Python ..

>>> a.itemsize
4

Приведенное выше значение дает представление о проблеме.Ваша строка имеет ширину всего 11 байт.11 не кратно 4. Но увеличение длины строки не даст вам массив {1,2,3,4,5,6} ... Я не уверен, что это даст вам.Почему неопределенность?Что ж, прочитайте приведенную ниже строку документации ... (уже поздно, поэтому я выделил важную часть, если вы засыпаете, как я!)

array.fromfile (f, n) Читать n элементов ( как машинные значения ) из файлового объекта f и добавить их в конец массива.Если доступно менее n элементов, вызывается EOFError, но доступные элементы по-прежнему вставляются в массив.f должен быть настоящим встроенным файловым объектом;что-то еще с методом read () не подойдет.

array.fromstring считывает данные так же, как array.fromfile.Обратите внимание на жирный шрифт выше.«как машинные значения» означает «читает как двоичный файл».Итак, чтобы делать то, что вы хотите, вам нужно использовать модуль struct.Проверьте приведенный ниже код.

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

Приведенный выше фрагмент кода загружает массив со значениями 1, 2, 3, 4;как мы и ожидаем.

Надеюсь, это поможет.

0 голосов
/ 19 ноября 2011
arr = []
arr = raw_input()

Если вы хотите разделить ввод пробелами:

arr = []
arr = raw_input().split()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...