3

次の 2 つの文字列があるとします。

Dim str1() As String = {"123", "456", "789", "0"}
Dim str2() As String = {"123", "456", "1"}

str1 と str2 の完全な外部結合を実行して、最終的に次のような構造になるにはどうすればよいですか。

{Nothing, "1"}
{"0", Nothing}
{"123", "123"}
{"456", "456"}
{"789", Nothing}

SO および他の Web サイトでのいくつかの議論に基づいて、LINQ を使用してみました。

Dim v = From a In str1 Join b In str2 On a Equals b Group By a Into g = Group
        From o In g.DefaultIfEmpty()

しかし、それはこれとまったく同じである望ましい結果を生成しません (通常の INNER JOIN):

Dim v = From a In str1 Join b In str2 On a Equals b

私が見ている最後の例はここにあります(C#)。

そして、ここに別の記事がありますが、可能な限り最短の解決策とするには複雑すぎるようです (もっと単純な C# の例を見てきたので、VB が同じように効率的であることを願っています)。

この質問が役立つ理由

たとえば、ファイルパスがキーであるファイル構造を持つことができます。キーの完全な外部結合を行うことにより、フォルダーを比較し、どのファイルがどちらの側で欠落しているかを見つけて、ユーザーに違いを示すことができます。あらゆる種類の同期タスクで、このアプローチを使用できます。

4

3 に答える 3

2

これはあなたが望む解決策ではないと思いますが、タスクを満たしているようです:

string[] a1 = { "123", "456", "1" };
string[] a2 = { "123", "456", "789", "0" };

var intersection = a1.Intersect(a2); //get the intersection
var exceptions1 = a1.Except(a2);     //get items from a1, that are not in a2
var exceptions2 = a2.Except(a1);     //get items from a2, that are not in a1

var result = new List<Tuple<string, string>>(); //the result set
result.AddRange(intersection.Select(s => new Tuple<string, string>(s, s)));
result.AddRange(exceptions1.Select(s => new Tuple<string, string>(s, null)));
result.AddRange(exceptions2.Select(s => new Tuple<string, string>(null, s)));

foreach (var t in result)
{
    Console.WriteLine((t.Item1 ?? "null") + "\t" + (t.Item2 ?? "null"));
}

出力は次のとおりです。

123     123
456     456
1       null
null    789
null    0
于 2013-01-18T01:35:47.187 に答える
1

HashSet、具体的には IntersectWithおよびSymmetricExceptWithメソッドを使用できます。

于 2013-01-18T01:38:33.380 に答える
0

わかりました、この答えはコンスタンチンのものと実際には機能的に違いはありませんが、スペースが小さくなっています。

私がしたことは、両方の配列でタプルへの外部結合を実行し、2 つの IEnumerables を結合することでした。

var str1 = new string[] { "123", "456", "789", "0" };
var str2 = new string[] { "123", "456", "1" };

var unionedsets = (from a in str1 join b in str2 on a equals b into grp from g in grp.DefaultIfEmpty()
            select new Tuple<string, string>(a, g)).Union(
            from b in str2 join a in str1 on b equals a into grp from g in grp.DefaultIfEmpty()
                select new Tuple<string,string>(g,b));

これほどコンパクトに見える唯一の理由は、LINQ ステートメントをまとめた (専門用語ですよね?) ためです。平滑化されていないコードは次のようになります。

var jstr1 = from a in str1
            join b in str2 on a equals b
            into grp
            from g in grp.DefaultIfEmpty()
            select new
            Tuple<string, string>(a, g);
var jstr2 = from b in str2
            join a in str1 on b equals a
            into grp
            from g in grp.DefaultIfEmpty()
            select new
            Tuple<string,string>(g,b);

var unionedjoin = jstr1.Union(jstr2);

これはあなたが探していたものに近いですか?

于 2013-01-18T03:10:55.130 に答える