3

こんにちは、XML ファイルから入力された 2 つの dataGridView テーブルで一意の文字列を見つけようとしています。私が作成したコードは問題なく実行されますが、テーブルの 1 つで文字列を変更 (一意にする) すると検出に失敗します。私の論理に何か問題がありますか?

    private void button5_Click(object sender, EventArgs e)
    {
        string[] column1 = new string[dataGridView1.Rows.Count];
        string[] column2 = new string[dataGridView2.Rows.Count];
        int unique = 0;
        bool found = false;
        for (int i = 0; i < dataGridView1.Rows.Count; i++)
        {
            column1[i] = Convert.ToString(dataGridView1.Rows[i].Cells[2].Value);
        }
        for (int i = 0; i < dataGridView2.Rows.Count; i++)
        {
            column2[i] = Convert.ToString(dataGridView2.Rows[i].Cells[2].Value);
        }
        for (int i = 0; i < column1.Length; i++)
        {
            for (int j = 0; j < column2.Length; j++)
            {
                if (column1[i] == column2[j])
                {
                    found = true;
                }
            }
            if (found == false)
            {
                unique++;
                found = false;
            }
        }
        MessageBox.Show(unique + " unique strings found!"); 
    }

最終的な解決策では、一意の文字列を含むセルを返して、それらをユーザーに強調表示できるようにする必要があります。助けてくれてどうもありがとう!

4

5 に答える 5

3

linqで簡単:

array1.Except(array2).Concat(array2.Except(array1))

あなたのコメントに応えて、2 つの左結合で完全な外部結合をシミュレートし、出力で null を探すことができます。反対側で一致しない結合の側は、一意であると見なすことができます。結合に次の拡張機能を使用します。

public static class LinqEx
{
    public static IEnumerable<TResult> 
        LeftOuterJoin<TOuter, TInner, TKey, TResult>(
            this IEnumerable<TOuter> outer, 
            IEnumerable<TInner> inner, 
            Func<TOuter, TKey> outerKeySelector, 
            Func<TInner, TKey> innerKeySelector, 
            Func<TOuter, TInner, TResult> resultSelector)
    {
        return outer
            .GroupJoin(
                inner, 
                outerKeySelector, 
                innerKeySelector, 
                (a, b) => new
                {
                    a,
                    b
                })
            .SelectMany(
                x => x.b.DefaultIfEmpty(), 
                (x, b) => resultSelector(x.a, b));
    }

    public static IEnumerable<TResult> 
        FullOuterJoin<TSet1, TSet2, TKey, TResult>(
            this IEnumerable<TSet1> set1, 
            IEnumerable<TSet2> set2, 
            Func<TSet1, TKey> set1Selector, 
            Func<TSet2, TKey> set2Selector, 
            Func<TSet1, TSet2, TResult> resultSelector)
    {
        var leftJoin = set1.
            LeftOuterJoin(
                set2, 
                set1Selector, 
                set2Selector, 
                (s1, s2) => new {s1, s2});
        var rightJoin = set2
            .LeftOuterJoin(
                set1, 
                set2Selector, 
                set1Selector, 
                (s2, s1) => new {s1, s2});
        return leftJoin.Union(rightJoin)
            .Select(x => resultSelector(x.s1, x.s2));

    }
}

次に、項目のインデックスやその取得元などの追加データを取得する匿名オブジェクトを作成し、それらを外部結合できます。結合の両側にアイテムがある結果は除外されます (両方のセットに存在するため)。結果セットには、セットの 1 つに固有のアイテムのみが含まれるようになりました。

void Main()
{
    var set1 = new[] {"a", "b", "c"};
    var set2 = new[] {"b", "c", "d", "d"};
    var annotatedSet1 = set1
        .Select((item,index) => new {src = "set1", index, item});
    var annotatedSet2 = set2
        .Select((item,index) => new {src = "set2", index, item});

    var uniques = annotatedSet1
        .FullOuterJoin(
            annotatedSet2, 
            x => x.item, 
            x => x.item,
            (s1, s2) => new {s1, s2})
        .Where(x => x.s1 == null || x.s2 == null)
        .Select(x => x.s1 ?? x.s2);
}

結果は次のようになります。

{src="set1", index=0, item="a"}
{src="set2", index=2, item="d"}
{src="set2", index=3, item="d"}
于 2012-08-22T13:18:33.423 に答える
0

を使用したLinqの方法は次のEnumerable.Exceptとおりです。

var dg1Cell2 = dataGridView1
    .Rows.Cast<DataGridViewRow>()
    .Select(r => r.Cells[2].Value.ToString());
var dg2Cell2 = dataGridView1
    .Rows.Cast<DataGridViewRow>()
    .Select(r => r.Cells[2].Value.ToString());
var uniqueInDG1 = dg1Cell2.Except(dg2Cell2);
var result = from r in dataGridView1.Rows.Cast<DataGridViewRow>()
             join u in uniqueInDG1 on r.Cells[2].Value.ToString() equals u
             select r;

Exceptセットの違いが生じるため、最初のシーケンスの一意の文字列のみが残ります。次に、結果を に結合しDataGridViewRowsます。

set内部で を使用しjoin、linq-to-objects も非常に効率的であることを除いて、すべて遅延して実行されるため、見た目よりも効率的です。

于 2012-08-22T13:20:08.850 に答える
0

リンク演算子、Union および Distinct 演算子を使用できます

var temp =  column1.Union(column2);
var result   = temp.Distinct();
于 2012-08-22T13:18:15.433 に答える
0

すべての返信に感謝しますが、単純な答えは、見つかった値を正しい時点で false にリセットしていないということでした。あなたのソリューションに費やされた努力に感謝しますが、それらはすべて私の知識レベルには複雑すぎます.

調整されたコードは次のとおりです。

    private void button5_Click(object sender, EventArgs e)
    {
        string[] column1 = new string[dataGridView1.Rows.Count];
        string[] column2 = new string[dataGridView2.Rows.Count];
        int unique = 0;
        bool found = false;
        for (int i = 0; i < dataGridView1.Rows.Count; i++)
        {
            column1[i] = Convert.ToString(dataGridView1.Rows[i].Cells[2].Value);
        }
        for (int i = 0; i < dataGridView2.Rows.Count; i++)
        {
            column2[i] = Convert.ToString(dataGridView2.Rows[i].Cells[2].Value);
        }
        for (int i = 0; i < column1.Length; i++)
        {
            for (int j = 0; j < column2.Length; j++)
            {
                if (column1[i] == column2[j])
                {
                    found = true;
                }
            }
            if (found == false)
            {
                unique++;
            }
            found = false;
        }
        MessageBox.Show(unique + " unique strings found!");         
    }
于 2012-08-22T13:54:37.097 に答える
0

次のコードは、2 つの文字列配列から個別の文字列配列を返します。

public string[] UniqueNames(string[] names1, string[] names2) {
    newName = names1.ToList();
    foreach (var dr in names2) {
        if (!newName.Contains(dr)) {
            newName.Add(dr);
        }
    }
    string[] newNameArray = newName.ToArray();
    return newNameArray;
}

または、試すこともできます。

public string[] UniqueNames(string[] names1, string[] names2) {            
    return names1.Union(names2).ToArray(); ;            
}
于 2020-12-19T13:04:51.517 に答える