1

2つの文字列を比較する方法について質問があります。

これがコードです。

        string stringA = "This is a test item";
        string stringB = "item test a is This";

明らかに、stringBにはstringAのすべての単語が含まれていますが、順序は異なります。

私の望む結果はTRUEになるはずです。

私の質問は、私は何をすべきかということです。.Contains()メソッドを使用しようとしましたが、結果はFALSEです。

みんな、ありがとう。

更新

親切な返信をありがとうございました。

これが私の説明です

実際にLINQとEFを使ってデータベース検索機能を構築しています。

アイテムの名前が「これはテストアイテムです」であるとします。

ユーザーが「testaisthis」と入力した場合、上記の項目をキャッチできるほどスマートな機能が欲しいです。

なにか提案を?

別の更新

あなたのご親切に感謝します。

Peter Ritchie、codesparkle、Dave、EdFredの提案が好きです。

4

9 に答える 9

6

スペース区切り文字を使用して単語を「String.Split」し、結果の配列をリストに並べ替えてから、リストを比較します。例えば:

var x = new List<string>(stringA.Split(' '));
x.Sort();
var y = new List<string>(stringB.Split(' '));
y.Sort();
bool areEqual = x.SequenceEqual(y);

大文字と小文字を区別しない場合:

var x = new List<string>(stringA.Split(' '));
x.Sort();
var y = new List<string>(stringB.Split(' '));
y.Sort();
bool areEqual = x.SequenceEqual(y, StringComparer.OrdinalIgnoreCase);

ただし、SQL Serverで実行されるものを探している場合は、別のものが必要になる可能性があります。

于 2012-08-14T02:47:32.850 に答える
4

このアプローチを試してください:

  • 各文字列の各単語を文字列の配列に取得します
  • 単語の各配列をアルファベット順に並べ替えます
  • 配列が等しいかどうかを比較します
于 2012-08-14T02:45:55.720 に答える
2

文字列をトークンに分割し、stringAのすべてのトークンがstringBのトークンリストに存在することをテストします。何かのようなもの:

var stringBTokens = stringB.Split(" ");
foreach(string token in stringA.Split(" "))
{
    if(stringBTokens.Contains(token) == false) return false;
}
return true;

これを行うことができる奇妙な正規表現があるかもしれませんが、これはかなり簡単なテストです。ファンシーになりたい場合は、LinqAnyメソッドを次のように使用できます。

var stringBTokens = stringB.Split(" ");
return !stringBTokens.Any(token => stringA.Contains(token));

これは基本的に同じことをしていますが、後者の方が少しエレガントだと思います。エラーがないことを願っています。私はMacbookProを使用しており、これが機能することを確認するために.net関連(またはモノラルなど)をインストールしていません。

アップデート

あなたの説明に基づいて、私はhttp://en.wikipedia.org/wiki/Inverted_indexを見てみます

これはあなたが達成しようとしていることのように聞こえます。私は以前にこれらを作成してデータベースで高速テキスト検索を実行しましたが、非常に効果的に機能します。

于 2012-08-14T02:54:08.960 に答える
2

バーナードの説明をモデルにしています。

多くの人が重要な部分を省略しました。比較する前に、文字列.ToLower()を変換する必要があります。

編集:これはあなたが必要なものです。Linqで読みやすくしました。

 public static bool Compare (string wordOne, string wordTwo)
    {
        //split into words
        var wordsOne = wordOne.ToLower().Split(' ').ToList();
        var wordsTwo = wordTwo.ToLower().Split(' ').ToList();

        if (wordsOne.Count() != wordsTwo.Count()) {
            return false;
        }

        //sort alphabetically
        wordsOne.Sort((x,y) => string.Compare(x, y));
        wordsTwo.Sort((x,y) => string.Compare(x, y));

        //compare
        for (int i = 0; i < wordsOne.Count(); i++) {
            if(wordsOne[i] != wordsTwo[i])
                return false;
        }

        return true;
    }
于 2012-08-14T02:55:18.597 に答える
1
stringA.OrderBy(c => c).SequenceEqual(stringB.OrderBy(c => c));

おっとを編集します。間違ったアプローチ。それは私にあまりにも速く答えることを教えてくれます。

私はこれがうまくいくと信じています:

stringA.Split(' ').OrderBy(w => w).SequenceEqual(stringB.Split(' ').OrderBy(w => w));
于 2012-08-14T02:46:12.373 に答える
1

私は2段階の比較を行います:

  1. .Split('')メソッドを使用して文字列を''で分割し、要素の数が同じであることを確認します(.Countプロパティ)。

  2. 新しく作成された配列(分割文字列)をSetsとしてキャストし、A set-difference B Union Bset-differenceAを実行します。

次に、テスト1に合格し、セットの差の和集合によって作成された要素がセットにない場合(テスト2)、上記のように文字列内の単語を正常に比較できました。

マイケルG。

于 2012-08-14T02:46:36.443 に答える
1

Peter Richieの優れた提案に基づいて、Array.Sort()代わりにを使用しList<T>.Sort()、重複することなく、きちんとした拡張方法に詰め込みました。

public static bool ContainsSameWordsAs(this string first, string second)
{
    return first.GetSortedWords().SequenceEqual(second.GetSortedWords());
    // if upper and lower case words should be seen as identical, use:
    // StringComparer.OrdinalIgnoreCase as a second argument to SequenceEqual
}

private static IEnumerable<string> GetSortedWords(this string source)
{
    var result = source.Split().ToArray();
    Array.Sort(result);
    return result;
}

使用法

string stringA = "This is a test item";
string stringB = "item test a is This";
string stringC = "Not the Same is This";
bool result = stringA.ContainsSameWordsAs(stringB);    // true
bool different = stringA.ContainsSameWordsAs(stringC); // false

編集: 質問に記載されている要件に準拠していない回答を受け入れた理由を理解するのは困難です。文字列を本当に一致させたい場合は"This is a test item""test a is this"次のようなもう少し複雑なものを使用する必要があります。

public static bool ContainsSameWordsAs(this string first, string second)
{
    var ignoreCase = StringComparer.OrdinalIgnoreCase;
    return first.Split().Any(word => second.Split().Contains(word, ignoreCase));
}

ただし、これは非常に緩いので、より良いアルゴリズムを考え出すことをお勧めします。一致としてカウントするには、2つの同一の単語で十分です。しかし、これは質問で述べられているようにあなたの要件に一致します。

于 2012-08-14T03:57:48.143 に答える
0

空白で文字列を分割し、結果の2つのコレクションを比較できます。linqからset操作を使用できます。

最初の文字列の単語がコレクションwords1にあり、2番目の文字列の単語がwords2にある場合、次の操作を実行できます。

if(!words1.Intersect(words2).Except( words1).Any()) -> your sentences are 'equal'
于 2012-08-14T02:47:08.413 に答える
0
        bool match = true;
        string[] stringBSplit = stringB.Split(' ');
        foreach (string aString in stringA.Split((' ')))
        {
            if (!stringBSplit.Contains(aString))
            {
                match = false;
                break;
            }
        }
于 2012-08-14T02:59:15.973 に答える