使用linq连续查找2个值

时间:2012-01-04 20:28:10

标签: c# linq

使用linq和这段代码做同样的事情会更容易吗? (检查并查看有多少值等于下面的值):

int[] values = {1,2,3,3,5,6,7};

int counter=0;
for (int f =0; f< values.Length-1; f++)
{
  if(values[f]==values[f+1])
  {
   counter++;
  }
}

6 个答案:

答案 0 :(得分:2)

是的,您可以使用.NET 4中的Zip轻松完成此操作:

var count = values.Zip(values.Skip(1), (x, y) => new { x, y })
                  .Count(pair => pair.x == pair.y);

结合ZipSkip(1)的诀窍需要一点点让你的头脑,但它是一个非常整洁的。基本上,您从一系列n值开始,结果是一对n - 1对,每个对都包含一个值及其后继值。

从那里开始,只需计算相同的对数:)

请注意,有问题的序列将被评估两次,因此您不希望对任何懒惰评估的内容执行此操作,或者在评估两次时不会给出相同的结果。

答案 1 :(得分:1)

不,我不认为这更容易。您拥有的代码易于理解和简洁,我不会用linq重构它。确保你测试一下,因为你可能会在最后一个循环中遇到一个越界错误。

答案 2 :(得分:1)

存在一个非常简洁的解决方案:

var list = new[] { 1, 2, 3, 3, 5, 6, 7, 7 };
var pairs = SeqModule.Pairwise(list);
var count = pairs.Count(p => p.Item1 == p.Item2);

这要求您引用程序集FSharp.Core并使用using Microsoft.FSharp.Collections;。或者,您可以将Pairwise方法实现为扩展方法,从而避免使用其他程序集。

对于可能对F#感兴趣的人,这是一个解决方案:

let lst = [1;2;3;3;5;6;7;7]
let count = lst |> Seq.pairwise
                |> Seq.filter (fun (x, y) -> x = y)
                |> Seq.length

答案 3 :(得分:0)

试试这个:

var set = values.Where((value, i) => i < (values.Length - 1) ? values[i] == values[i + 1] : false);

编辑:

抱歉,忘了添加set.Count()来获得结果: - )

答案 4 :(得分:0)

鉴于值在数组中,您可以这样做:

int duplicates = values.Skip(1).Where((n, i) => n == values[i]).Count();

答案 5 :(得分:0)

你可以这样说:

private static int CountDoubles( IEnumerable<int> Xs )
{
  int?  prev  = null ;
  int   count = Xs.Count( curr => {
    bool isMatch = prev.HasValue && prev == curr ;
    prev = curr ;
    return isMatch ;
  } ) ;

  return count ;
}

但这比原始版本既简单也不简洁。我会略微调整你的,但是::

public static int CountDoubles( int[] Xs )
{
  int n = 0 ;

  for ( int i = 1 ; i < Xs.Length ; ++i )
  {
    n += ( Xs[i-1] == Xs[i] ? 1 : 0 ) ;
  }

  return n ;
}