给出以下两个字符串:
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#)。
这里是Another article,但它似乎太复杂而不是最短的解决方案(我已经看到了更简单的C#示例,希望VB可以效率很高)。
为什么这个问题很有用
例如,可以有一个文件结构,其中文件路径是一个键。通过执行键的完全外连接,您可以比较文件夹,查找哪一侧缺少哪些文件并向用户显示差异。任何类型的同步任务都可以使用这种方法。
答案 0 :(得分: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
答案 1 :(得分:1)
您可以使用HashSet,特别是IntersectWith
和SymmetricExceptWith
方法。
答案 2 :(得分:0)
好吧,这个答案在功能上与Konstantin不同,但在空间上却更小。
我所做的是将两个数组上的外连接执行到元组并将两个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);
这更接近你想要的吗?