Instead of splitting and filtering, you could use np.fromstring:
>>> np.fromstring(b, sep='\t').reshape(-1, 4)
array([[ 191.25 , 0. , 0. , 1. ],
[ 191.251, 0. , 0. , 1. ],
[ 191.252, 0. , 0. , 1. ]])
This always returns a 1D array so reshaping is necessary.
Alternatively, to avoid reshaping, if you already have a string of bytes (as strings are in Python 2), you could use np.genfromtxt (with the help of the standard library's io module):
>>> import io
>>> np.genfromtxt(io.BytesIO(b))
array([[ 191.25 , 0. , 0. , 1. ],
[ 191.251, 0. , 0. , 1. ],
[ 191.252, 0. , 0. , 1. ]])
genfromtxt handles missing values, as well as offering much more control over how the final array is created.
Instead of splitting and filtering, you could use np.fromstring:
>>> np.fromstring(b, sep='\t').reshape(-1, 4)
array([[ 191.25 , 0. , 0. , 1. ],
[ 191.251, 0. , 0. , 1. ],
[ 191.252, 0. , 0. , 1. ]])
This always returns a 1D array so reshaping is necessary.
Alternatively, to avoid reshaping, if you already have a string of bytes (as strings are in Python 2), you could use np.genfromtxt (with the help of the standard library's io module):
>>> import io
>>> np.genfromtxt(io.BytesIO(b))
array([[ 191.25 , 0. , 0. , 1. ],
[ 191.251, 0. , 0. , 1. ],
[ 191.252, 0. , 0. , 1. ]])
genfromtxt handles missing values, as well as offering much more control over how the final array is created.
Here's what I did to get the result you're looking for:
import numpy as np
b='191.250\t0.00\t0\t1\n191.251\t0.00\t0\t1\n191.252\t0.00\t0\t1\n'
a = np.array([[float(j) for j in i.split('\t')] for i in b.splitlines()])
Don't replace your "row delimiters" by "column delimiters". Instead, for split the string on the row delimiter. Then split each row on the column delimiter.
If your input has new line characters:
rows = data.split()
If your input has a literal backslash followed by the letter n rather than a newline character:
rows = data.split('\\n')
Either way, now you can split each row on commas:
matrix = [row.split(',') for row in rows]
save this str to string like s then :
s='''459,2277,617459268\n14619,99,19600737\n11297,99,18666551\n16603,99,19761406\n12660,99,28741324\n4543'''
for i in s.split('\n'):
print (i)
459,2277,617459268
14619,99,19600737
11297,99,18666551
16603,99,19761406
12660,99,28741324
4543
or if you want to print without , :
for i in s.replace(',' , ' ').split('\n'):
print (i)
459 2277 617459268
14619 99 19600737
11297 99 18666551
16603 99 19761406
12660 99 28741324
4543
Given that the 2D list string happens to be valid syntax for a Python 2D list, you could just use the eval() function:
output = eval("[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]")
print(output)
print(output[0])
This prints:
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
[1, 0, 0, 0]
In [4]: import ast
In [5]: array = "[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]"
In [6]: array = ast.literal_eval(array)
In [7]: array
Out[7]: [[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
ast.literal_eval(node_or_string)[Python-doc]Safely evaluate an expression node or a string containing the following Python literal :: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.
The challenge is to save not only the data buffer, but also the shape and dtype. np.fromstring reads the data buffer, but as a 1d array; you have to get the dtype and shape from else where.
In [184]: a=np.arange(12).reshape(3,4)
In [185]: np.fromstring(a.tostring(),int)
Out[185]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [186]: np.fromstring(a.tostring(),a.dtype).reshape(a.shape)
Out[186]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
A time honored mechanism to save Python objects is pickle, and numpy is pickle compliant:
In [169]: import pickle
In [170]: a=np.arange(12).reshape(3,4)
In [171]: s=pickle.dumps(a*2)
In [172]: s
Out[172]: "cnumpy.core.multiarray\n_reconstruct\np0\n(cnumpy\nndarray\np1\n(I0\ntp2\nS'b'\np3\ntp4\nRp5\n(I1\n(I3\nI4\ntp6\ncnumpy\ndtype\np7\n(S'i4'\np8\nI0\nI1\ntp9\nRp10\n(I3\nS'<'\np11\nNNNI-1\nI-1\nI0\ntp12\nbI00\nS'\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x0e\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x16\\x00\\x00\\x00'\np13\ntp14\nb."
In [173]: pickle.loads(s)
Out[173]:
array([[ 0, 2, 4, 6],
[ 8, 10, 12, 14],
[16, 18, 20, 22]])
There's a numpy function that can read the pickle string:
In [181]: np.loads(s)
Out[181]:
array([[ 0, 2, 4, 6],
[ 8, 10, 12, 14],
[16, 18, 20, 22]])
You mentioned np.save to a string, but that you can't use np.load. A way around that is to step further into the code, and use np.lib.npyio.format.
In [174]: import StringIO
In [175]: S=StringIO.StringIO() # a file like string buffer
In [176]: np.lib.npyio.format.write_array(S,a*3.3)
In [177]: S.seek(0) # rewind the string
In [178]: np.lib.npyio.format.read_array(S)
Out[178]:
array([[ 0. , 3.3, 6.6, 9.9],
[ 13.2, 16.5, 19.8, 23.1],
[ 26.4, 29.7, 33. , 36.3]])
The save string has a header with dtype and shape info:
In [179]: S.seek(0)
In [180]: S.readlines()
Out[180]:
["\x93NUMPY\x01\x00F\x00{'descr': '<f8', 'fortran_order': False, 'shape': (3, 4), } \n",
'\x00\x00\x00\x00\x00\x00\x00\x00ffffff\n',
'@ffffff\x1a@\xcc\xcc\xcc\xcc\xcc\xcc#@ffffff*@\x00\x00\x00\x00\x00\x800@\xcc\xcc\xcc\xcc\xcc\xcc3@\x99\x99\x99\x99\x99\x197@ffffff:@33333\xb3=@\x00\x00\x00\x00\x00\x80@@fffff&B@']
If you want a human readable string, you might try json.
In [196]: import json
In [197]: js=json.dumps(a.tolist())
In [198]: js
Out[198]: '[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]'
In [199]: np.array(json.loads(js))
Out[199]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
Going to/from the list representation of the array is the most obvious use of json. Someone may have written a more elaborate json representation of arrays.
You could also go the csv format route - there have been lots of questions about reading/writing csv arrays.
'[[ 0.5544 0.4456], [ 0.8811 0.1189]]'
is a poor string representation for this purpose. It does look a lot like the str() of an array, but with , instead of \n. But there isn't a clean way of parsing the nested [], and the missing delimiter is a pain. If it consistently uses , then json can convert it to list.
np.matrix accepts a MATLAB like string:
In [207]: np.matrix(' 0.5544, 0.4456;0.8811, 0.1189')
Out[207]:
matrix([[ 0.5544, 0.4456],
[ 0.8811, 0.1189]])
In [208]: str(np.matrix(' 0.5544, 0.4456;0.8811, 0.1189'))
Out[208]: '[[ 0.5544 0.4456]\n [ 0.8811 0.1189]]'
I'm not sure there's an easy way to do this if you don't have commas between the numbers in your inner lists, but if you do, then you can use ast.literal_eval:
import ast
import numpy as np
s = '[[ 0.5544, 0.4456], [ 0.8811, 0.1189]]'
np.array(ast.literal_eval(s))
array([[ 0.5544, 0.4456],
[ 0.8811, 0.1189]])
EDIT: I haven't tested it very much, but you could use re to insert commas where you need them:
import re
s1 = '[[ 0.5544 0.4456], [ 0.8811 -0.1189]]'
# Replace spaces between numbers with commas:
s2 = re.sub('(\d) +(-|\d)', r'\1,\2', s1)
s2
'[[ 0.5544,0.4456], [ 0.8811,-0.1189]]'
and then hand on to ast.literal_eval:
np.array(ast.literal_eval(s2))
array([[ 0.5544, 0.4456],
[ 0.8811, -0.1189]])
(you need to be careful to match spaces between digits but also spaces between a digit an a minus sign).
That works, but if your only goal is to implement fire(x, y), then NumPy is overkill.
def fire(x, y):
return grid[3 * y + x]
A few issues:
- Probably better to follow pep8
- This isn't a method, it is a function
- When doing 2D
numpyindexes, you can dotwoDArray[x, y] - You don't really need a numpy array, a list of lists works just as well. Or better yet just just translate the 2D index into a linear index mathematically. This also avoids the substantial overhead of converting the list to a numpy array. You could even use
np.ravel_multi_indexto do the 2D to 1D conversion for you.
You could use np.fromstring setting a space as separator and reshape to the desired shape:
np.fromstring(s, sep=' ').reshape(20, 20)
Or as a more general solution:
rows = s.count('\n') + 1
np.fromstring(s, sep=' ').reshape(-1, rows)
More general for any 2D grid:
rows = s.count('\n') + 1
np.fromstring(s, sep=' ').reshape(rows, -1)
Wrap each line in one more pair of brackets, then pass to a suitable eval function:
import ast
arr = []
with open('input.txt', 'r') as infp:
for l in infp:
arr.append(ast.literal_eval('[%s]' % l)) # replace with eval() if you trust your input data
print(arr)
Output:
[[[0, 0, 0, 1, 1], [0, 0, 0, 0, 0], [0, 1, 1, 0, 0], [1, 0, 0, 0, 0]], [[1, 0, 0, 1, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0]]]
And a little explanation, as requested:
- Since each line in the input file is of the form
[1,2],[3,4]and a Python list-of-lists would be[[1, 2], [3, 4]],'[%s]'is used to wrap the line in that one more pair of brackets to make it valid Python. ast.literal_eval()is a safe form ofeval()that only accepts literals (no function calls or other such things).So all in all, for a line
[1, 2], [3, 4], the effective code iseval('[[1, 2], [3, 4]]').
text = 'a,b,c'
text = text.split(',')
text [ 'a', 'b', 'c' ]