1

目標は、テキスト (つまり、スピーチ) を並べ替え、スピーチ内の個別の単語のリストをテキスト ボックスに出力することです。私はボード上の多くのヒントを読んで、たくさん遊びましたが、この時点で、私が始めたときよりも混乱しています. これが私のコードです

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

    }

この時点で、1 つの単語が返されます。私が使用しているテキスト (gettysburg アドレス) では、それは「年」という単語であり、テキスト内でその単語の唯一のインスタンスです。

文字列配列にロードされた個々の単語を関数に渡し、それをリストに入れます (これは冗長かもしれません)。

4

4 に答える 4

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));
    }
}
于 2013-02-23T19:34:59.383 に答える
0

あなたの質問に関するいくつかのヒント:

  • IEnumerable<T>LINQ 拡張メソッドは、配列とリストの両方によって実装される で定義されているため、配列をリストに変換する理由はありません。
  • すべての文字が同じ大文字/小文字であることを確認してください - たとえば、ToLower を使用します
  • すべての反復で txtOutput.Text を上書きしています。新しい値を設定する代わりに、新しい部分を既存の値に追加します

必要な出力を生成する簡単なコードは次のとおりです。

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

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

関連するメモとして、テキスト全体が 1 つの文字列として指定されている、テキストから個別の単語を返す非常に単純な 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

于 2015-06-08T09:27:49.343 に答える
-1

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# の型付き配列はinterface を実装します)。IList<T>

AppendLineメソッド(および のほとんどのメソッド)は、操作が実行されたStringBuilderのインスタンスを返します。これが、メソッド呼び出しが機能する理由です。操作を呼び出して結果を返すだけです (返される各項目は同じ参照になります)。StringBuilderLastOrDefault

builderCopy変数は、変更されたクロージャへのアクセスを回避するために使用されます(安全であることは決して問題ではありません)。

最後の null チェックは、wordList要素が含まれていない場合のためのものです。この場合、 への呼び出しLastOrDefaultは null を返します。

于 2013-02-23T03:39:35.713 に答える