Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 扩散集的LINQ_C#_Linq - Fatal编程技术网

C# 扩散集的LINQ

C# 扩散集的LINQ,c#,linq,C#,Linq,我有以下阵列: var original= new int[] { 2, 1, 3 }; var target = new int[] { 1, 3, 4 }; enum Operation {Added,Removed} 我想执行一个LINQ查询,该查询将返回以下内容: {{2,Removed},{4,Added}} 限制:我希望LINQ能够非常高效地执行此操作,并避免和O(n^2)风格的算法 你运气不好。如您在评论中所述,如果列表未排序,则无法计算您在单个正向传递中寻求的差异。考虑: {

我有以下阵列:

var original= new int[] { 2, 1, 3 };
var target = new int[] { 1, 3, 4 };
enum Operation {Added,Removed}
我想执行一个LINQ查询,该查询将返回以下内容:

{{2,Removed},{4,Added}}

限制:我希望LINQ能够非常高效地执行此操作,并避免和O(n^2)风格的算法

你运气不好。如您在评论中所述,如果列表未排序,则无法计算您在单个正向传递中寻求的差异。考虑:

{ 1, 2, 3, 4, 5, 6, 7, ...
{ 1, 2, 3, 6, 7, 8, 9, ...
在遇到第一个差异时(4对6),您不可能确定是否要删除4和5(如果两个列表都是单调递增的,则是这样),或者插入6、7、8和9,如果列表继续这样,则是这样:

{ 1, 2, 3,             4, 5, 6, 7, 8, 9,...
{ 1, 2, 3, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9,...

在这种情况下,LINQ解决方案可能不是最好的选择

这将生成一个具有所需结果的词典

Dictionary<int, Operation> difference = new Dictionary<int,Operation>();
foreach (int value in original) {
    difference.Add(value, Operation.Removed);
}
foreach (int value in target) {
    if (difference.ContainsKey(value)) {
        difference.Remove(value);
    } else {
        difference.Add(value, Operation.Added);
    }
}
字典差异=新字典();
foreach(原始的int值){
差异。添加(值、操作。删除);
}
foreach(目标中的int值){
if(差分容器(值)){
差异。删除(值);
}否则{
差异。添加(值、操作。添加);
}
}
为了减小字典的大小,也许可以并行循环枚举。我来看看

编辑:
这是:

Dictionary<int, Operation> difference = new Dictionary<int,Operation>();
IEnumerator<int> o = ((IEnumerable<int>)original).GetEnumerator();
IEnumerator<int> t = ((IEnumerable<int>)target).GetEnumerator();
bool oActive=true, tActive=true;
while (oActive || tActive) {
    if (oActive && (oActive = o.MoveNext())) {
        if (difference.ContainsKey(o.Current)) {
            difference.Remove(o.Current);
        } else {
            difference.Add(o.Current, Operation.Removed);
        }
    }
    if (tActive && (tActive = t.MoveNext())) {
        if (difference.ContainsKey(t.Current)) {
            difference.Remove(t.Current);
        } else {
            difference.Add(t.Current, Operation.Added);
        }
    }
}
字典差异=新字典();
IEnumerator o=((IEnumerable)original).GetEnumerator();
IEnumerator t=((IEnumerable)目标).GetEnumerator();
bool-oActive=true,tActive=true;
while(主动的| |触觉的){
如果(oActive&&(oActive=o.MoveNext()){
if(电流差){
差异。移除(o.电流);
}否则{
差异。添加(o.当前,操作。删除);
}
}
if(tActive&(tActive=t.MoveNext()){
if(差分容器(t电流)){
差分。移除(t.电流);
}否则{
差异.添加(t.当前,操作.添加);
}
}
}
编辑2:
我做了一些性能测试。第一个版本运行速度提高了10%-20%,包括排序列表和随机排序列表

我列出了从1到100000的数字列表,随机跳过了10%的数字。在我的机器上,第一个版本的代码在大约16毫秒内与列表匹配

enum Operation { Added, Removed, }

static void Main(string[] args)
{
    var original = new int[] { 2, 1, 3 };
    var target = new int[] { 1, 3, 4 };

    var result = original.Except(target)
        .Select(i => new { Value = i, Operation = Operation.Removed, })
        .Concat(
            target.Except(original)
            .Select(i => new { Value = i, Operation = Operation.Added, })
            );

    foreach (var item in result)
        Console.WriteLine("{0}, {1}", item.Value, item.Operation);
}

我不认为在给定股票LINQ扩展方法的情况下,您可以只使用一次通过就可以使用LINQ实现这一点,但您可能能够编写一个自定义扩展方法来实现。您的权衡可能是延迟执行的损失。比较两者的相对性能会很有意思。

这将在一个简单的过程中实现结果然而,我不确定GroupBy操作的复杂性

var original= new int[] { 1, 2, 3 };
var target = new int[] { 1, 3, 4 };

var output = original.Select( i => new { I = i, L = "o" } )
    .Concat( target.Select( i => new { I = i, L = "t" } ) )
    .GroupBy( i => i.I ).Where( i => i.Count() == 1 )
.Select( i => new { I = i.Key, S = (i.ElementAt( 0 ).L == "o" ? Operation.Removed : Operation.Added) } );

如果有一个比使用LINQ更好的解决方案,你能解释一下你的需求的原因吗?当然,我经常比较两个长长的项目列表来寻找更新,所以我需要在这里进行扩展。另外,SymmetriceExceptWith并没有真正解决这个问题……yerp,这几乎就是我想要的解决方案,但我将尝试并封装它很好的扩展方法,对…使它看起来像LINQ…;)这比我的基准测试中的字典慢了大约30%,但它更简洁,就像group by stuff不能很好地扩展。这比字典解决方案慢8倍。我担心可能是这样。Enumerable.Range(51000);vs可枚举范围(0,10000);