如何在 C# 中使用 LINQ 返回非重复单词列表

本文关键字:返回 列表 单词 LINQ | 更新日期: 2023-09-27 18:00:45

目标是对文本(即演讲(进行排序,并将语音中不同单词的列表输出到文本框中。 我已经阅读了很多关于棋盘的技巧,玩了很多,但在这一点上,我比开始时更困惑。 这是我的代码

   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";
        }
    }

在这一点上,我得到了一个词的回报。 对于我使用的文本(葛底斯堡地址(,它是"年"这个词,它是文本中该词的唯一实例。

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

如何在 C# 中使用 LINQ 返回非重复单词列表

我希望它以简单有效的方式满足您的需求(使用 .Dump(( from LINQPad(

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));
    }
}

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

  • 没有理由将数组转换为列表,因为 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
}

您可以在此处找到针对同一问题的正则表达式模式的更多变体:正则表达式和 LINQ 查询,用于将文本拆分为不同的单词

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

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());
}

您可以使用 StringBuilder 类具有流畅的接口以及 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> 接口(。

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

builderCopy变量用于避免访问修改后的闭包(安全永远不会受到伤害(。

末尾的 null 检查适用于wordList不包含任何元素的情况。 在这种情况下,对LastOrDefault的调用将返回 null。