如何在C#中使用LINQ返回不同单词列表?

时间:2013-02-23 02:36:31

标签: c# .net linq

目标是对文本(即语音)进行分类,并将语音中不同单词的列表输出到文本框。我已经阅读了很多关于电路板的提示并且玩了很多但是在这一点上,当我开始时,我更加困惑。这是我的代码

   private void GenerateList(string[] wordlist)
    {
       List<string> wordList = new List<string>();

        for (int i = 0; i < wordlist.Length; i++)
        {
            wordList.Add(wordlist[i]);
        }

        var uniqueStr = from item in wordList.Distinct().ToList()
                        orderby item
                        select item;


        for (int i = 0; i < uniqueStr.Count(); i++ )
        {
            txtOutput.Text = uniqueStr.ElementAt(i) + "\n";
        }

    }

此时我得到了一个单词的回报。对于我正在使用的文本(gettysburg地址),它是单词“year”,它是文本中该单词的唯一实例。

我将每个单词加载的函数传递给一个字符串数组,然后将其放入一个列表中(这可能是多余的?)。

4 个答案:

答案 0 :(得分:1)

我希望这能以简单有效的方式完成您所需要的工作(使用LINQPad中的.Dump())

void Main()
{
    // can be any IEnumerable<string> including string[]
    var words = new List<string>{"one", "two", "four", "three", "four", "a", "z"};

    words.ToDistinctList().Dump();

    // you would use txtOutput.Text = words.ToDistinctList()
}

static class StringHelpers
{
    public static string ToDistinctList(this IEnumerable<string> words)
    {
        return string.Join("\n", new SortedSet<string>(words));
    }
}

答案 1 :(得分:0)

关于您的问题的一些提示:

  • 没有理由将数组转换为列表,因为LINQ扩展方法是在IEnumerable<T>上定义的,它由数组和列表实现
  • 确保所有字母都在相同的情况下 - 例如使用ToLower
  • 您在每次迭代中都会覆盖txtOutput.Text。而不是设置新值,而是将新零件附加到现有值

以下是生成所需输出的简单代码:

IEnumerable<string> distinct =
    wordList
    .Select(word => word.ToLower())
    .Distinct()
    .OrderBy(word => word);

txtOutput.Text = string.Join("\n", distinct.ToArray());

在相关的说明中,这是一个非常简单的LINQ表达式,它返回文本中的不同单词,其中整个文本被指定为一个字符串:

public static IEnumerable<string> SplitIntoWords(this string text)
{

    string pattern = @"\b[\p{L}]+\b";

    return
        Regex.Matches(text, pattern)
            .Cast<Match>()                          // Extract matches
            .Select(match => match.Value.ToLower()) // Change to same case
            .Distinct();                            // Remove duplicates

}

您可以在此处找到针对同一问题的正则表达式模式的更多变体:Regex and LINQ Query to Split Text into Distinct Words

答案 2 :(得分:-1)

以下是我如何简化代码以及实现您想要实现的目标。

private void GenerateList(string[] wordlist)
{
   List<string> wordList = wordlist.ToList(); // initialize the list passing in the array


    var uniqueStr = from item in wordList.Distinct().ToList()
                    orderby item
                    select item;


    txtOutput.Text = String.Join("\n", uniqueStr.ToArray());
}

答案 3 :(得分:-1)

您可以使用StringBuilder class具有流畅的界面以及LINQ来大大简化这一事实。

首先,您可以创建StringBuilder并将所有单词连接到同一个实例中,如下所示:

// The builder.
var builder = new StringBuilder();

// A copy of the builder *reference*.
var builderCopy = builder;

// Get the distinct list, order by the string.
builder = wordList
    // Get the distinct elements.
    .Distinct()
    // Order the words.
    .OrderBy(w => w).
    // Append the builder.
    Select(w => builderCopy.AppendLine(word)).
    // Get the last or default element, this will
    // cycle through all of the elements.
    LastOrDefault();

// If the builder is not null, then assign to the output, otherwise,
// assign null.
txtOutput.Text = builder == null ? null : builder.ToString();

注意,您不必实际实现列表,因为wordList 已经一个物化列表,它是一个数组(并且作为旁注,C#中的类型化数组实现IList<T> interface)。

AppendLine method(以及StringBuilder上的大多数方法)返回执行操作的StringBuilder实例,这就是LastOrDefault method调用工作的原因;只需调用操作并返回结果(返回的每个项目都是相同的引用)。

builderCopy变量用于避免access to a modified closure(从不伤害安全)。

最后的空检查是针对wordList不包含任何元素的情况。在这种情况下,对LastOrDefault的调用将返回null。