从分类的短语列表中提取频率数据

pro*_*ian 5 text wolfram-mathematica

在对列表操作的文档/过去问题进行管道调查后,我发现空白 - 许多案例涉及数字,而我正在处理大量文本.

我有一个常见的三字短语(三字母)的排序列表,它出现在大量的文本信息中,通过Mathematica的Partition [],Tally []和Sort []命令生成.我正在操作的数据类型的一个示例(我有数百个这样的文件):

{{{wa,wa,wa},66},{{i,love,you},62},{{la,la,la},50},{{meaning,of,life},42},{ on,come,on},40},{{come,on,come},40},{{是的,是的,是的},38},{{不,不,不是},36},{{我们, re,gonna},36},{{you,love,me},35},{{in,love,with},32},{{the,way,you},30},{{i,want,and to},30},{{back,to,me},29},<< 38211 >>,{{of,an,xke},1}}

我希望搜索这个文件,这样如果输入是"意义,生命",它将返回"42".我觉得我必须忽略一些明显的东西,但在修补过后我在这里碰了一堵砖墙.Mathematica在其文档中数量很多,这是......好吧,不足为奇.

Leo*_*rin 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}};
Run Code Online (Sandbox Code Playgroud)

以下是创建哈希表的一种可能方法:

Clear[trigramHash];
(trigramHash[Sequence @@ #1] = #2) & @@@ trigrams;
Run Code Online (Sandbox Code Playgroud)

现在,我们使用它

In[16]:= trigramHash["meaning","of","life"]
Out[16]= 42
Run Code Online (Sandbox Code Playgroud)

当然,如果您执行许多搜索,这种方法将是有益的.

编辑

如果你有很多文件并希望在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
Run Code Online (Sandbox Code Playgroud)

DumpSave用来创建一个.mx文件.因此,建议的过程是将数据加载到Mathematica,逐个文件,创建哈希(您可以使用SubValues索引特定哈希表索引文件的索引),然后将这些定义保存到.mx文件中.通过这种方式,您可以快速加载和快速搜索,并且您可以自由决定在任何给定时间将数据的哪一部分保存到Mathematica中(几乎没有性能损失,通常与文件加载相关).


Sim*_*mon 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;
Run Code Online (Sandbox Code Playgroud)

哪个(如果你愿意)你可以包含一个与Leonid有类似行为的函数

In[3]:= trigram[seq__String] := {seq} /. trigramRules

In[4]:= trigram["meaning", "of", "life"]

Out[4]= 42
Run Code Online (Sandbox Code Playgroud)

由于您有一个非常大的对列表,因此可以通过使用来加速生成的规则的应用Dispatch.也就是说,除了定义trigramRules使用外,其他所有内容都与上面相同

trigramRules = Dispatch[Rule @@@ trigrams]
Run Code Online (Sandbox Code Playgroud)


Dan*_*lau 5

这是将字符串中的单个单词放入列表的一种方法.

In[262]:= str = "meaning, of, life"; ReadList[
 StringToStream[str], Word, WordSeparators -> {",", " "}]

Out[262]= {"meaning", "of", "life"}
Run Code Online (Sandbox Code Playgroud)

您可以在案例或其他形式的查找中使用它来获得42结果(非常可疑,那个数字......)

---编辑---

通过"查找",我想到了Leonid Shifrin所展示的那种机制.我不确定遇到的困难是,或者只是从字符串转换为三元组列表.我(仅)展示了管理后者的方法.

---结束编辑---

---编辑2 ---

评论显示了避免ReadList的方法.让我说明我欣喜若狂,我设法找到了这种方法.下面是我在原始响应中输入的代码,然后在我意识到有更简洁的代码时被替换.

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"}
Run Code Online (Sandbox Code Playgroud)

底线(几乎字面意义):我可以找到其他人的复杂方法,并且比大多数人更好.

---结束编辑---

Daniel Lichtblau