7

次のような文字列のリストがあるとします。

var candidates = new List<String> { "Peter", "Chris", "Maggie", "Virginia" };

List<String>ここで、別の(それを呼びましょうlist1)に、これらの候補のそれぞれが1回だけ含まれていることを確認したいと思います。どうすればそれを簡潔に行うことができますか?使えると思いますIntersect()。また、行方不明の候補者を取得したいと思います。

private bool ContainsAllCandidatesOnce(List<String> list1)
{
     ????
}


private IEnumerable<String> MissingCandidates(List<String> list1)
{
     ????
}

順序は関係ありません。

4

7 に答える 7

5

これは速度の点では最適ではないかもしれませんが、どちらのクエリも1行に収まるほど短く、理解しやすいものです。

private bool ContainsAllCandidatesOnce(List<String> list1)
{
    return candidates.All(c => list1.Count(v => v == c) == 1);
}

private IEnumerable<String> MissingCandidates(List<String> list1)
{
    return candidates.Where(c => list1.Count(v => v == c) != 1);
}
于 2012-05-09T00:11:01.080 に答える
2

ここでは、 ExceptIntersectDistinctについて話します。式でランバ演算子を使用することもできますが、すべての項目をループする必要があります。その機能は、事前定義された機能で使用できます。

あなたの最初の方法のために

var candidates = new List<String> { "Peter", "Chris", "Maggie", "Virginia" };

private bool ContainsAllCandidatesOnce(List<String> list1)
{
    list1.Intersect(candidates).Distinct().Any();
}

これにより、候補リストで共通のlist1の要素が提供されます。または、他の方法で実行することもできます。

candidates.Intersect(list1).Distinct().Any();

2番目の方法

private IEnumerable<String> MissingCandidates(List<String> list1)
{
    list1.Except(candidates).AsEnumerable();
}

これにより、候補に含まれるすべての要素がlist1から削除されます。あなたがそれを他の方法で望むならあなたはそれをすることができます

candidates.Except(list1).AsEnumerable();
于 2012-05-09T00:58:12.620 に答える
1

これは非常に効率的です。

IEnumerable<string> strings  = ...

var uniqueStrings = from str in strings
                    group str by str into g
                    where g.Count() == 1
                    select g.Key;

var missingCandidates = candidates.Except(uniqueStrings).ToList();
bool isValid = !missingCandidates.Any();
  1. 繰り返しを除外します。
  2. すべての候補がフィルターされたセットで発生することを確認します。
于 2012-05-09T00:12:55.870 に答える
1

GroupJoinは、この仕事に適したツールです。msdnから:

GroupJoinは階層的な結果を生成します。これは、外部の要素が内部の一致する要素のコレクションとペアになっていることを意味します。GroupJoinを使用すると、外部の各要素の一致セット全体に基づいて結果を作成できます。

外側の特定の要素の内側に相関要素がない場合、その要素の一致のシーケンスは空になりますが、結果には引き続き表示されます。

したがって、GroupJoinは、ソース内の各アイテムについて、ターゲットから一致するものをすべて検索します。ターゲットに一致するものが見つからない場合、ソース内のアイテムはフィルタリングされません。代わりに、それらは空のグループに一致します。

Dictionary<string, int> counts = candidates
 .GroupJoin(
   list1,
   c => c,
   s => s,
   (c, g) => new { Key = c, Count = g.Count()
 )
 .ToDictionary(x => x.Key, x => x.Count);

List<string> missing = counts.Keys
  .Where(key => counts[key] == 0)
  .ToList();

List<string> tooMany = counts.Keys
  .Where(key => 1 < counts[key])
  .ToList();
于 2012-05-09T14:14:22.193 に答える
0
    private bool ContainsAllCandidatesOnce(List<String> list1)
    {
        return list1.Where(s => candidates.Contains(s)).Count() == candidates.Count();
    }

    private IEnumerable<String> MissingCandidates(List<String> list1) 
    {
        return candidates.Where(s => list1.Count(c => c == s) != 1);
    } 
于 2012-05-09T00:09:27.433 に答える
0

Listの代わりにHashSetを使用するのはどうですか?

于 2012-05-09T01:51:52.140 に答える
-1
private static bool ContainsAllCandidatesOnce(List<string> lotsOfCandidates)
{
    foreach (string candidate in allCandidates)
    {
        if (lotsOfCandidates.Count(t => t.Equals(candidate)) != 1)
        {
            return false;
        }
    }

    return true;
}

private static IEnumerable<string> MissingCandidates(List<string> lotsOfCandidates)
{
    List<string> missingCandidates = new List<string>();

    foreach (string candidate in allCandidates)
    {
        if (lotsOfCandidates.Count(t => t.Equals(candidate)) != 1)
        {
            missingCandidates.Add(candidate);
        }
    }

    return missingCandidates;
}
于 2012-05-10T03:08:37.887 に答える