3

给定以下两个字符串:

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 和其他网站上的几次讨论,我尝试使用 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

我一直在看的最后一个例子是here(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,特别是 IntersectWithandSymmetricExceptWith方法。

于 2013-01-18T01:38:33.380 回答
0

好吧,这个答案与康斯坦丁的答案在功能上并没有什么不同,但它在空间上更小。

我所做的是将两个数组的外部连接执行为元组并将两个 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 语句组合在一起(这是一个技术术语,对吗?)。Unsmooshed,代码如下所示:

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 回答