Как читать stdin в массив 2D python целых чисел?

Я хотел бы прочитать 2d-массив целых чисел из stdin (или из файла) в 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.читать()) ValueError: длина строки не кратна размеру элемента

3 ответов


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

С помощью 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]]

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

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

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

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

>>> a.itemsize
4

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

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

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

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

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

надеюсь, что это помогает.


arr = []
arr = raw_input()

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

arr = []
arr = raw_input().split()