我正在使用CERN的pyROOT模块做一些工作,我正在尝试将一个字符串数组存储为二叉树中的一个叶子。为了做到这一点,我必须传递一个数组,显然,使用不是列表或字典,而是数组模块。该模块支持标准C数组,字符,整数等,但有没有人知道我可以嵌套它们的方式,以便有一个字符串数组,或者,有效地,一个字符数组数组?或者我走得太远了,我需要从键盘上退后一步:)?
代码:
import ROOT
rowtree = ROOT.TTree("rowstor", "rowtree")
ROOT.gROOT.ProcessLine(
"struct runLine {\
Char_t test[20];\
Char_t test2[20];\
};" );
from ROOT import runLine
newline = runLine()
rowtree.Branch("test1", newline, "test/C:test2")
newline.test = ["AbcDefgHijkLmnOp","aaaaaaaaaaaaaaaaaaa"]
rowtree.Fill()
错误:
python branchtest
Traceback (most recent call last):
File "branchtest", line 14, in <module>
newline.test = ["AbcDefgHijkLmnOp","aaaaaaaaaaaaaaaaaaa"]
TypeError: expected string or Unicode object, list found
我想知道是否可以将此示例中显示的列表转换为字符串数组。
答案 0 :(得分:3)
char数组和Python字符串的Python列表是两个非常不同的东西。
如果你想要一个包含char数组(一个字符串)的分支,那么我建议使用Python的内置bytearray
类型:
import ROOT
# create an array of bytes (chars) and reserve the last byte for null
# termination (last byte remains zero)
char_array = bytearray(21)
# all bytes of char_array are zeroed by default here (all b'\x00')
# create the tree
tree = ROOT.TTree('tree', 'tree')
# add a branch for char_array
tree.Branch('char_array', char_array, 'char_array[21]/C')
# set the first 20 bytes to characters of a string of length 20
char_array[:21] = 'a' * 20
# important to keep the last byte zeroed for null termination!
tree.Fill()
tree.Scan('', '', 'colsize=21')
tree.Scan('', '', 'colsize=21')
的输出是:
************************************
* Row * char_array *
************************************
* 0 * aaaaaaaaaaaaaaaaaaaa *
************************************
所以我们知道树正在接受字节。
如果您想存储字符串列表,那么我建议使用std::vector<std::string>
:
import ROOT
strings = ROOT.vector('string')()
tree = ROOT.TTree('tree', 'tree')
tree.Branch('strings', strings)
strings.push_back('Hello')
strings.push_back('world!')
tree.Fill()
tree.Scan()
tree.Scan()
的输出是:
***********************************
* Row * Instance * strings *
***********************************
* 0 * 0 * Hello *
* 0 * 1 * world! *
***********************************
在循环中,您需要strings.clear()
才能在下一个条目中填写新的字符串列表。
现在,rootpy包(也参见存储库on github)提供了一种在Python中创建树的更好方法。下面是一个如何使用rootpy以“友好”的方式使用char数组的示例:
from rootpy import stl
from rootpy.io import TemporaryFile
from rootpy.tree import Tree, TreeModel, CharArrayCol
class Model(TreeModel):
# define the branches you want here
# with branchname = branchvalue
char_array = CharArrayCol(21)
# the dictionary is compiled and cached for later
# if not already available
strings = stl.vector('string')
# create the tree inside a temporary file
with TemporaryFile():
# all branches are created automatically according to your model above
tree = Tree('tree', model=Model)
tree.char_array = 'a' * 20
# attemping to set char_array with a string of length 21 or longer will
# result in a ValueError being raised.
tree.strings.push_back('Hello')
tree.strings.push_back('world!')
tree.Fill()
tree.Scan('', '', 'colsize=21')
tree.Scan('', '', 'colsize=21')
的输出是:
***********************************************************************
* Row * Instance * char_array * strings *
***********************************************************************
* 0 * 0 * aaaaaaaaaaaaaaaaaaaa * Hello *
* 0 * 1 * aaaaaaaaaaaaaaaaaaaa * world! *
***********************************************************************
在此处查看另一个使用带有rootpy的TreeModel
的示例:
https://github.com/rootpy/rootpy/blob/master/examples/tree/model_simple.py
答案 1 :(得分:0)
您已将test
的{{1}}成员定义为20个字符数组:
runLine
但是你要尝试传递一个包含两个字符串的列表:
Char_t test[20];\
这在C(或CINT)或Python中没有任何意义,所以当然它在PyROOT中也没有任何意义。
此外,您的问题中似乎存在很多混淆。你说你需要传递PyROOT“一个数组,很明显,不是使用列表或字典,而是使用数组模块”......但是PyROOT并不特别关心Python newline.test = ["AbcDefgHijkLmnOp","aaaaaaaaaaaaaaaaaaa"]
模块。您已标记了您的问题array
,这意味着您可能会将numpy
而不是numpy
视为“阵列模块”,但上次我检查了(当然,这是很久以前),他们根本没有互动;如果你想要传递给PyROOT的东西,你必须明确要求numpy导出缓冲区。