0

Visual C# 2010 Express を使用しています。過去にどのペアの学生が一緒に働いたかを教えてくれる学生の配列があります。したがって、arrStudents(0,0) には Joe が含まれ、arrStudents(0,1) には Bob が含まれる場合があり、その逆の場合もあります。名前が記録されている順序は関係ありません。気にするのはペアリング情報だけです。

例:

Joe - Bob
Mary - Bob
Bob - Joe
Mary - Joe
Jack - Mary
Joe - Bob

すべての異なるペアを識別し、それが何回発生したかをカウントするには、どの方法を使用すればよいですか?

したがって、(Joe - Bob) と (Bob - Joe) は同じペアであるため、結果は次のようになります。

Joe - Bob, 3
Mary - Bob, 1
Mary - Joe, 1
Jack - Mary, 1
4

3 に答える 3

6

Dictionaryキーが学生ペアで、値がカウントである を作成します。次に、すべてのペアを繰り返し処理し、辞書に追加します。ペアごとに、名前をアルファベット順 (または何でも) に並べ替えて、"Joe-Bob" と "Bob-Joe" の両方が "Bob-Joe" になるようにします。ペアが辞書に既に存在する場合は、対応する値を 1 増やします。存在しない場合は、追加して値を 1 に設定します。最後に、辞書を反復処理するだけで結果が得られます。

于 2012-09-05T19:07:53.773 に答える
4
List<Tuple<string, string>> list = new List<Tuple<string, string>>()
{
    //Joe - Bob Mary - Bob Bob - Joe Mary - Joe Jack - Mary Joe - Bob
    new Tuple<string,string>("Joe","Bob"),
    new Tuple<string,string>("Mary","Bob"),
    new Tuple<string,string>("Bob","Joe"),
    new Tuple<string,string>("Mary","Joe"),
    new Tuple<string,string>("Jack","Mary"),
    new Tuple<string,string>("Joe","Bob")
};

var result = list.GroupBy(x=>x, new MyComparer())
    .Select(g=>new {Count = g.Count(),Pair = g.First()})
    .ToArray();

--

public class MyComparer : IEqualityComparer<Tuple<string, string>>
{
    public bool Equals(Tuple<string, string> x, Tuple<string, string> y)
    {
        return (x.Item1 == y.Item1 && x.Item2 == y.Item2) ||
            (x.Item2 == y.Item1 && x.Item1 == y.Item2);
    }

    public int GetHashCode(Tuple<string, string> obj)
    {
        return obj.Item1.GetHashCode() ^ obj.Item2.GetHashCode();
    }
}
于 2012-09-05T19:10:25.403 に答える
0

私が考えることができる最も簡単な方法は、小さなLinqです。まず、表示されているものと同様に、すべての学生のペアを文字列のペアのリストとして取得します。動作するList<Tuple<string, string>>はずです。注意が必要な点は、長方形の配列を使用していることです。これを IEnumerable として扱うと、奇妙なアクセス動作が発生します。

次に、2 つのペアが等しいかどうかを比較する方法が必要です。比較に使用するラムダ ステートメントを指定できるジェネリック クラスがあるので、カスタム比較ごとに単一目的の IEqualityComparer を実装する必要はありません。

public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
    private readonly Func<T, T, bool> equalityComparer;
    private readonly Func<T, int> hashFunc;

    public GenericEqualityComparer(Func<T, T, bool> compareFunc, Func<T,int> hashFunc)
        :this(compareFunc)
    {
        this.equalityComparer = compareFunc;
        this.hashFunc = hashFunc;
    }

    public GenericEqualityComparer(Func<T, T, bool> compareFunc)
    {
        this.equalityComparer = compareFunc;
        this.hashFunc = o => o.GetHashCode();
    }

    public bool Equals(T x, T y)
    {
        return equalityComparer(x, y);
    }

    public int GetHashCode(T obj)
    {
        return hashFunc(obj);
    }
}

次に、Linq の GroupBy() メソッドを介して値のリストを実行し、GenericEqualityComparer を指定して、カスタムの順序に依存しない方法で値を比較します。

var pairCounts = pairList
                    .GroupBy(p=>p, //key selector; we want the Tuple itself
                       new GenericEqualityComparer<Tuple<string,string>>(
                          (a,b)=>(a.Item1 == b.Item1 && a.Item2 == b.Item2) 
                             || (a.Item1 == b.Item2 && a.Item2 == b.Item1))
                    .Select(g=>new Tuple<string, int>(g.Key.Item1 + " - " + g.Key.Item2,
                                                      g.Count());

最終結果は、List<Tuple<string,int>>見つかった名前の各ペアの最初の順列と、そのペアのいずれかの順列がリスト内でいくつ見つかったかを含む になります。

于 2012-09-05T19:16:48.823 に答える