如何确定单词在多个句子中出现的位置?

时间:2015-03-03 14:19:59

标签: matlab matrix

我有以下代码告诉我一个单词出现在句子中的次数。具体来说,我有一个单元格的句子字符串数组和一个单词单元格数组,我想用它来搜索每个句子。此代码是一个2D单元格数组,其中每个行和列组合告诉我在一个句子(行)中看到特定单词(列)出现的次数。换句话说:

Out = NaN(numel(sentences), numel(out_words));
   for i = 1:numel(out_words)    
   Out(:,i) = cellfun(@(x) numel(strfind(x, out_words{i})), sentences);
end

display(Out)

我现在想要的是1D单元格数组Out,其中每个元素描述一个单词,在此元素中是一个向量,告诉您单词出现在哪个句子中。

例如,如果单词treestrees的ID分配为1,则Out{1}的单元格元素中的潜在向量可能为[1,5,8],意味着单词trees出现在句子1,5和8中。有没有办法在MATLAB中执行此操作?

1 个答案:

答案 0 :(得分:1)

我将重申我在评论中提出的问题,以便StackOverflow社区的人们知道问题的真正含义:


OP想要一个单元格数组Out,其中每个元素都描述一个单词,在这个元素中是一个向量,告诉你单词出现在哪个句子中。

例如,如果单词treestrees的ID分配为1,则Out{1}的单元格元素中的潜在向量可能为[1,5,8],意味着单词树出现在句子1,5和8中。


执行此操作的一种简单方法是循环遍历您拥有的每个单词并使用strfind并查看输出中的哪些元素非空。对于那些非空的位置,这将确定单词在特定句子中的位置。我们举个例子。我将选择六个句子作为Bruce CockburnLovers in a Dangerous Time的前六个歌词。我将声明它在一个名为sentences的字符串的单元格数组中。为了确保我们能够正确找到单词并且不担心大小写,我们会将所有句子转换为小写lower

sentences = {'Don''t the hours grow shorter as the days go by',
'You never get to stop and open your eyes'
'One day you''re waiting for the sky to fall'
'The next you''re dazzled by the beauty of it all'
'When you''re lovers in a dangerous time'
'Lovers in a dangerous time'};

sentences = lower(sentences);

接下来,我将声明一个words数组,用于确定我想要在所有句子中找到哪些单词:

words = {'you', 'one', 'dangerous', 'beauty', 'go', 'to'};

因此,您想要的代码非常简单:

Out = cell(numel(words), 1); %// Declare empty array of cells for each word
for idx = 1 : numel(words) %// For each word...
    K = strfind(sentences, words{idx}); %// See which sentences have these words
    ind = cellfun('isempty', K); %// Determine which locations are EMPTY
    Out{idx} = find(~ind); %// To find those locations that are non-empty, we need to find those entries that are 0, so search for the inverse
end

让我们慢慢浏览上面的代码。我们首先声明一个元素(1D)的单元格数组,它与我们拥有的单词总数一样长。接下来,对于每个单词,我们使用strfind来确定我们是否可以在所有句子中找到该特定单词。 strfind将返回一个单元格数组,其中此数组中的每个元素都会告诉您我们找到此单词的起始索引(或索引是否存在多个匹配项)。如果此单元格数组中的元素为空,则表示我们未在句子中找到该单词。

现在,我们接下来要做的是在此单元格数组中搜索的任何条目。这可以使用cellfun来完成,输出将是logical向量,其中1表示它为空,0表示它是非空的。我们希望找到非空的位置,因此我们使用find来搜索非空的位置。这些地点最终决定我们是否在该句中找到了这个词。

因此,如果我们运行上面的例子,这就是我们得到的:

>> celldisp(Out)

Out{1} =

     2

Out{2} =

     3

Out{3} =

     5
     6

Out{4} =

     4

Out{5} =

     1 

Out{6} =

     2
     3

这意味着对于第一个单词you,我们在句子#2中找到了这个单词,即:'you never get to stop and open your eyes'。接下来,第二个单词是one,我们在句子#3中找到了这个单词,其中包含:'one day you're waiting for the sky to fall'。下一个单词是dangerous,我们在句子#5和#6中找到了这个单词,其中包含:'when you're lovers in a dangerous time'和  'lovers in a dangerous time'。您可以跟随单元格数组的其余部分,您可以验证每个单元格元素给您的是句子ID,告诉您每个单词出现的位置。

在你的评论中,你想进一步做一个关联数组,你指定你想要的字符串,输出将是包含这些单词的句子的句子ID。您可以使用containers.Map类为您执行此操作。具体做法是:

out_dict = containers.Map(words, Out);

现在,你可以这样做:

>> out_dict('dangerous')

ans =

     5
     6

如果您想输入多个单词,请使用values方法:

vals = values(out_dict, {'you', 'dangerous', 'go'})
celldisp(vals)

vals{1} =

     2

vals{2} =

     5
     6

vals{3} =

     1

如果您想显示所有单词,请执行以下操作:

vals = values(out_dict, words);    
celldisp(vals)

vals{1} =

     2

vals{2} =

     3

vals{3} =

     5
     6    

vals{4} =

     4

vals{5} =

     1

vals{6} =

     2
     3

顺便说一句,我会为你重申一遍。请考虑接受之前问题中提供给您的答案。这表示StackOverflow社区您不再需要帮助来解决您的问题。由于您喜欢阅读答案,因此您可以阅读本文以帮助您了解如何接受答案:How to update and accept answers

祝你好运!