Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.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_Asp Classic - Fatal编程技术网

C# 使用LINQ获取列表之间的差异并将其插入列表之间?

C# 使用LINQ获取列表之间的差异并将其插入列表之间?,c#,linq,asp-classic,C#,Linq,Asp Classic,假设我有一个这样的列表:1,4,6,8 我想知道它们之间的大小差异,有简单的LINQ解决方案吗? 所以我会得到3,2,2(因为4-1,6-4等)作为最终的列表: 1,3,4,2,6,2,8 有人知道我是怎么用linq编码的吗? 对于我实际需要它们的原因,这是一个带有DateTime(不是int)的结构列表。我首选的解决方案是使用zip var result = list.Zip(list.Skip(1), (current, next) => Math.Abs(next - current

假设我有一个这样的列表:1,4,6,8

我想知道它们之间的大小差异,有简单的LINQ解决方案吗? 所以我会得到3,2,2(因为4-1,6-4等)作为最终的列表: 1,3,4,2,6,2,8

有人知道我是怎么用linq编码的吗?
对于我实际需要它们的原因,这是一个带有DateTime(不是int)的结构列表。

我首选的解决方案是使用zip

var result = list.Zip(list.Skip(1), (current, next) => Math.Abs(next - current))
这将获取一个列表和不包含第一个元素的同一个列表,并在它们都具有当前位置的元素时对它们进行迭代,从而生成每对之间差值的绝对值

编辑:刚刚意识到你想把它插回去。那样的话

var result = 
  list
    .Zip(list.Skip(1), (current, next) => new[]{current, current - next, next})
    .SelectMany(x => x);

…可能是你想要的,尽管现在越来越乱了。您最好压缩到一个新对象中,或者不使用SelectMany,这样您就可以拥有
{current,difference,next}
的单个集合,因为这些集合更容易处理。

这里是一个非LINQ解决方案。我不知道哪一个表现更好

            var l = new List<int>() {1, 4, 6, 13};
            var resultSet = new List<int>();

            var enumerator = l.GetEnumerator();
            enumerator.MoveNext();
            var prev = enumerator.Current;
            while(enumerator.MoveNext())
            {
                resultSet.Add(enumerator.Current - prev);
                prev = enumerator.Current;
            }
var l=newlist(){1,4,6,13};
var resultSet=新列表();
var枚举器=l.GetEnumerator();
枚举数。MoveNext();
var prev=枚举数。当前值;
while(枚举数.MoveNext())
{
结果集.Add(enumerator.Current-prev);
prev=枚举数。当前值;
}

因此,首先,我们可以使用一种方法,该方法可以获取任意序列,并将每个项目与其前一个项目配对,这对于任何序列的一般情况来说都很容易编写:

public static IEnumerable<TResult> Pairwise<TSource, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, TSource, TResult> resultSelector)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            yield break;
        var previous = iterator.Current;
        while (iterator.MoveNext())
        {
            yield return resultSelector(previous, iterator.Current);
            previous = iterator.Current;
        }
    }
}

还有另一个变体-像这样使用聚合扩展

var s = new List<int>(){1, 4, 6, 8};
var tt = s.Aggregate(new List<int>(), (a, b) => {
             if (a.Count % 2 != 0)
             {
                 a.Add(b - a[a.Count - 1]);
             }
             a.Add(b);
             return a; 
         });
var s=newlist(){1,4,6,8};
var tt=s.Aggregate(新列表(),(a,b)=>{
如果(a.计数%2!=0)
{
a、 加上(b-a[a.Count-1]);
}
a、 添加(b);
返回a;
});
更新第2版

var s = new List<int>(){1, 4, 6, 8};
var tt = s.Aggregate(new List<int>(), (a, b) => {
             var c = new List<int>(a);
             if (c.Count % 2 != 0)
             {
                 c.Add(b - c[c.Count - 1]);
             }
             c.Add(b);
             return c; 
         });
var s=newlist(){1,4,6,8};
var tt=s.Aggregate(新列表(),(a,b)=>{
var c=新列表(a);
如果(c.计数%2!=0)
{
c、 加上(b-c[c.Count-1]);
}
c、 添加(b);
返回c;
});
foreach版本

var s = new List<int>(){1, 4, 6, 8};
var tt = new List<int>();
foreach(var i in s){
    if (tt.Count % 2 != 0)
        {
            tt.Add(i - tt[tt.Count - 1]);
        }
    tt.Add(i);
 }
var s=newlist(){1,4,6,8};
var tt=新列表();
foreach(s中的var i){
如果(tt.Count%2!=0)
{
tt.Add(i-tt[tt.Count-1]);
}
tt.添加(i);
}
用于的版本

var s = new List<int>(){1, 4, 6, 8};
var tt = new List<int>(){s[0]};
for (int i=1;i<s.Count,i++){
     tt.Add(s[i] - s[i-1]);
     tt.Add(s[i]);
 }
var s=newlist(){1,4,6,8};
var tt=new List(){s[0]};

对于(int i=1;ii如果它是一个
日期时间的列表,你会如何得到两者之间的差异?它不能包含3,2…因为它们是整数值,它只能包含日期时间值。我有一个方法来给出时间跨度和相应的“长度”。如果我知道如何对int列表进行此操作,我确信我可以使其工作。你如何lan组合两个结果。如果您有日期,则两个日期之间的差异是一个间隔。您不能将日期和间隔混合到同一序列中。对于整数,两个整数之间的差异是另一个整数,因此可以工作。请注意,此解决方案将源序列迭代两次。对于没有问题的列表,而是对于其他序列它可能是,所以你应该小心不要将它应用于任何任意序列。@Servy:据我所知,这只会一起迭代序列一次。这就是为什么较短序列结束时Zip结束。Zip同时迭代源序列和第二序列。在这种情况下,这意味着同时迭代
list
list.Skip(1)
。这两种方法都涉及到迭代
列表
。如果它是一个实际的列表,这很好,但是如果它是一个DB查询,那么你将访问数据库两次,而不是一次。你实际上并没有在这里聚合任何数据,你只是在对数据进行迭代。你可以使用几乎任何你想要的操作符,因为大多数操作符都是iter删除源序列;您只是依赖于副作用。您应该使用
foreach
循环,以使代码的意图更清晰。@Servy副事件是什么?副作用是向列表中添加一项。@Servy此处不更改原始列表,此处添加累加器或更正,但您正在变异累加器,这意味着您依赖于方法的副作用。如果您的聚合函数对每个项多次调用它的函数,它将中断。这是一种很容易看出它依赖于副作用的方法。真正的聚合不会改变累加器,而是用一个完全n的函数替换累加器每次ew项,因此累积方法的签名。
var s = new List<int>(){1, 4, 6, 8};
var tt = new List<int>(){s[0]};
for (int i=1;i<s.Count,i++){
     tt.Add(s[i] - s[i-1]);
     tt.Add(s[i]);
 }