在对文档/过去的列表操作问题进行管理之后,我发现空白 - 许多案例涉及数字,而我正在处理大量文本。
我有一个常见的三字短语(三字母)的排序列表,它出现在大量的文本信息中,通过Mathematica的Partition [],Tally []和Sort []命令生成。我正在操作的数据类型的一个示例(我有数百个这样的文件):
{{{wa,wa,wa},66},{{i,love,you},62},{{la,la,la},50},{{含义,生命},42 },{on,come,on},40},{{come,on,come},40},{{yeah,yeah,yeah},38},{{no,no,no},36},{ {we,re,gonna},36},{{you,love,me},35},{{in,love,with},32},{{the,way,you},30},{{i ,want,to},30},{{back,to,me},29},<<< 38211>>,{{of,an,xke},1}}
我希望能够搜索这个文件,这样如果输入是“生命的意义”,它将返回“42”。我觉得我必须忽略一些显而易见的东西,但在修补过后我在这里碰了一堵砖墙。 Mathematica在其文档中数量很多,这是......好吧,并不令人惊讶。
答案 0 :(得分:6)
假设您可以以您概述的形式将数据加载到Mathematica中,一个非常简单的事情是创建一个哈希表,其中您的三元组将是(复合)键。这是你的样本(你给出的部分):
trigrams = {{{"wa", "wa", "wa"}, 66}, {{"i", "love", "you"}, 62},
{{"la", "la", "la"}, 50}, {{"meaning", "of", "life"}, 42},
{{"on", "come", "on"}, 40}, {{"come", "on", "come"}, 40},
{{"yeah", "yeah", "yeah"}, 38}, {{"no", "no", "no"}, 36},
{{"we", "re", "gonna"}, 36}, {{"you", "love", "me"}, 35},
{{"in", "love", "with"}, 32}, {{"the", "way", "you"}, 30},
{{"i", "want", "to"}, 30}, {{"back", "to", "me"}, 29},
{{"of", "an", "xke"}, 1}};
以下是创建哈希表的一种可能方法:
Clear[trigramHash];
(trigramHash[Sequence @@ #1] = #2) & @@@ trigrams;
现在,我们像
一样使用它In[16]:= trigramHash["meaning","of","life"]
Out[16]= 42
当然,如果您执行多次搜索,这种方法将非常有用。
修改强>
如果您有许多文件并希望在Mathematica中有效地搜索它们,您可以做的一件事就是使用上面的散列机制将所有文件转换为.mx
二进制Mathematica文件。这些文件针对快速加载进行了优化,并作为要存储的定义的持久性机制。以下是它的工作原理:
In[20]:= DumpSave["C:\\Temp\\trigrams.mx",trigramHash]
Out[20]= {trigramHash}
In[21]:= Quit[]
In[1]:= Get["C:\\Temp\\trigrams.mx"]
In[2]:= trigramHash["meaning","of","life"]
Out[2]= 42
您使用DumpSave
创建.mx
文件。因此,建议的过程是将数据加载到Mathematica,逐个文件,创建哈希(您可以使用SubValues
索引具有文件索引的特定哈希表),然后将这些定义保存到{ {1}}个文件。通过这种方式,您可以快速加载和快速搜索,并且您可以自由决定在任何给定时间将数据的哪一部分保存到Mathematica中(几乎没有性能损失,通常与文件加载相关)。
答案 1 :(得分:5)
这可能没有Leonid给出的解决方案那么快,但你可以将你的对列表变成一个规则列表。
In[1]:= trigrams = {{{"wa", "wa", "wa"}, 66}, {{"i", "love", "you"},
62}, {{"la", "la", "la"}, 50}, {{"meaning", "of", "life"},
42}, {{"on", "come", "on"}, 40}, {{"come", "on", "come"},
40}, {{"yeah", "yeah", "yeah"}, 38}, {{"no", "no", "no"},
36}, {{"we", "re", "gonna"}, 36}, {{"you", "love", "me"},
35}, {{"in", "love", "with"}, 32}, {{"the", "way", "you"},
30}, {{"i", "want", "to"}, 30}, {{"back", "to", "me"},
29}, {{"of", "an", "xke"}, 1}};
In[2]:= trigramRules = Rule @@@ trigrams;
哪个(如果你愿意)你可以包含一个与Leonid的行为类似的函数
In[3]:= trigram[seq__String] := {seq} /. trigramRules
In[4]:= trigram["meaning", "of", "life"]
Out[4]= 42
由于您有一个非常大的对列表,因此可以使用Dispatch
加速生成的规则的应用。也就是说,除了使用
trigramRules
之外,请执行与上述相同的所有操作
trigramRules = Dispatch[Rule @@@ trigrams]
答案 2 :(得分:5)
这是将字符串中的单个单词放入列表的一种方法。
In[262]:= str = "meaning, of, life"; ReadList[
StringToStream[str], Word, WordSeparators -> {",", " "}]
Out[262]= {"meaning", "of", "life"}
您可以在案例或其他形式的查询中使用它来获得42结果(非常可疑,那个数字......)
---编辑---
通过“查找”,我想到了Leonid Shifrin所展示的那种机制。我不确定遇到的困难是,或者只是从字符串转换为三元组列表。我(仅)展示了管理后者的方法。
---结束编辑---
---编辑2 ---
评论显示了避免阅读列表的方法。让我说明我欣喜若狂,我设法找到了这种方法。下面是我在原始响应中添加的代码,然后在我意识到有更简洁的代码时被替换。
str = "meaning, of, life";
commaposns = StringPosition[str, ", "];
substrposns =
Partition[
Join[{1},
Riffle[commaposns[[All, 1]] - 1, commaposns[[All, 2]] + 1], {-1}],
2];
substrs = Map[StringTake[str, #] &, substrposns]
Out[259]= {"meaning", "of", "life"}
底线(几乎字面意思):我可以找到其他人的复杂方法,并且比大多数方法更好。
---结束编辑---
Daniel Lichtblau
答案 3 :(得分:1)
相当古老的问题..但现在我们有Association
lookup = Association[Rule @@@ trigrams];
lookup[{"come", "on", "come"}]
40
甚至
lookup = Association[
Rule[StringJoin@Riffle[#1, " "], #2] & @@@ trigrams]
lookup["meaning of life"]
42