我知道该功能将包含大量数据处理,但我认为最终不会花费很多细节来处理。

有问题的函数被馈入一个锯齿状2D数组,该数组由“段落”>“句子”组成,该数组是由用户馈送的文本文件制成的,因此可能很大。它使用此数组,将每个句子彼此进行比较,并保存每个句子之间的分数,即常见单词的数量。

这需要永远,我坦白地认为不会。

我的主要测试文本只有181个句子,但这意味着在2D数组中得分为3.27万个值。

然后,该值矩阵用于从每个段落和其他内容中计算和选择最“相关”的句子。

181个句子的文本需要1分15秒来处理,只有70个句子的文本需要35秒,但这是基于句子的数量而不是单词,但是它给了您一个想法。我担心要花多长时间才能完成一份实际文件。

有问题的功能:

    protected void Intersection2DArray()
    {
        mainSentenceCoord = -1;
        for (int x1 = 0; x1 < results.Length; x1++)
        {
            for (int x2 = 0; x2 < results[x1].Length; x2++)
            {
                var mainSentencesWords = wordSplit(results[x1][x2]);
                secondarySentenceCoord = -1;
                mainSentenceCoord++;

                for (int y1 = 0; y1 < results.Length; y1++)
                {
                    for (int y2 = 0; y2 < results[y1].Length; y2++)
                    {
                        var secondarySentencesWords = wordSplit(results[y1][y2]);
                        int commonElements = mainSentencesWords.Intersect(secondarySentencesWords).ToList().Count();
                        secondarySentenceCoord++;
                        intersectionArray[mainSentenceCoord, secondarySentenceCoord] = commonElements;
                    }
                }
            }
        }
    }


wordSplit函数:

        protected List<String> wordSplit(string sentence)
        {
            var symbols = "£$€#&%+-.";
            var punctuationsChars = Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue)
                                        .Select(i => (char)i)
                                        .Where(c => char.IsPunctuation(c))
                                        .Except(symbols)
                                        .ToArray();

            var words = sentence.Split(punctuationsChars)
                             .SelectMany(x => x.Split())
                             .Where(x => !(x.Length == 1 && symbols.Contains(x[0])))
                             .Distinct()
                             .ToList();
            return words;
        }


我最初想使用一个Regex行进行此拆分,但不会弄清楚,这可能会使它更快。

这样循环选择彼此相对的每个句子,这是我最好的选择。如果可以大幅度提高速度,那么我总体上会很好。

编辑:使用Moby Disk建议在这里是我的新即时代码:

Word Split函数,该函数现在被调用一次并返回列表列表

    public List<List<string>> createWordList()
    {
        List<List<string>> wordList = new List<List<string>>();
        var symbols = "£$€#&%+-.";
        var punctuationsChars = Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue)
                                    .Select(i => (char)i)
                                    .Where(c => char.IsPunctuation(c))
                                    .Except(symbols)
                                    .ToArray();

        for (int x1 = 0; x1 < results.Length; x1++)
        {
            for (int x2 = 0; x2 < results[x1].Length; x2++)
            {
                var words = results[x1][x2].Split(punctuationsChars)
                                            .SelectMany(x => x.Split())
                                            .Where(x => !(x.Length == 1 && symbols.Contains(x[0])))
                                            .Distinct()
                                            .ToList();
                wordList.Add(words);
            }
        }
        return wordList;
    }


现在超薄的交叉口功能

    protected void intersectionMatrix()
    {
        List<List<string>> wordList =  createWordList();
        mainSentenceCoord = -1;
        for (var x = 0; x < wordList.Count; x++)
        {
            secondarySentenceCoord = -1;
            mainSentenceCoord++;
            for (var y = 0; y < wordList.Count; y++)
            {
                secondarySentenceCoord++;
                intersectionArray[mainSentenceCoord, secondarySentenceCoord] = wordList[x].Intersect(wordList[y]).Count();
            }
        }
    }

最佳答案

请参阅最后的更新:

这里有一些“低落的果实”,可以在不更改算法本身的情况下加快速度:


每次调用wordSplit()都会重新计算“标点符号”。一次做一次。
您正在为同一句子调用wordSplit()N ^ 2次而不是N次,因为它同时在外部(x1,x2)循环和内部(y1,y2)循环中。您只需要拆分181个句子,而无需拆分181 ^ 2个句子。因此,请遍历结果,在每个句子上调用一次wordSplit,然后存储该结果。如果这占用过多内存,请查看记忆(http://en.wikipedia.org/wiki/Memoization),尽管我认为您应该没问题,因为它只会导致多出大约1份文本。
您在Intersect()之后不需要ToList()。这将创建一个您不使用的列表。


我对mainSentenceCoord和secondarySentenceCoord的值感到困惑。结果交集数组的尺寸是多少?

我的天啊! #1是!这使速度提高了80倍。看这行:

Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue)


char.MaxValue是65536。因此,如果N = 181,则循环181 x 181 x 65536!我只是运行了探查器来确认它:98.4%的CPU时间花费在wordSplit的ToArray()调用中。

关于c# - 嵌套循环功能需要几分钟才能运行,反正可以提高效率?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28221449/

10-12 17:20