LINQ可以用来查找排序列表中的空白吗?

时间:2010-11-24 18:39:34

标签: c# .net linq sorting .net-3.5

我是否有可能以允许我确定“9”的方式使用LINQ  是不使用for循环并将每个值与相邻值相比较的排序列表中的第一个缺失值?

var listStringVals = new [] { "7", "13", "8", "12", "10", "11", "14" };
// sort list to "7","8","10","11","12","13","14"
var sortedList = listStringVals.OrderBy(c => int.Parse(c)).ToList();
// need some magic here to get the first gap in the sorted list

7 个答案:

答案 0 :(得分:59)

var strings = new string[] { "7", "13", "8", "12", "10", "11", "14" };

然后

var list = Array.ConvertAll(strings, s => Int32.Parse(s)).OrderBy(i => i);
// or
var list = strings.Select(s => int.Parse(s)).OrderBy(i => i);
// or
var list = strings.OrderBy(s => int.Parse(s));

(注意this问题)

然后

var result = Enumerable.Range(list.Min(), list.Count).Except(list).First(); // 9
// or
int min = list.Min(), max = list.Max();
var result = Enumerable.Range(min, max - min + 1).Except(list).First();

答案 1 :(得分:11)

这是一种让你入门的方法(我在这里使用int值):

List<int> listStringVals = (new int[] { 7, 13, 8, 12, 10, 11, 14 }).ToList();
List<int> SortedList = listStringVals.OrderBy(c => c).ToList();
List<int> Gaps = Enumerable.Range(SortedList.First(), 
                                  SortedList.Last() - SortedList.First() + 1)
                           .Except(SortedList).ToList();

答案 2 :(得分:4)

var listStringVals = new string[] {"7", "13", "8", "12", "10", "11", "14"};
var sortedInts = listStringVals.Select(c => int.Parse(c)).OrderBy(x => x);
var noGaps = Enumerable.Range(sortedInts.First(), 
                              sortedInts.Last() - sortedInts.First() + 1);
var missing = noGaps.Except(sortedInts).Select(x => x.ToString()).First();

编辑:感谢BeemerGuy's answer生成固定范围。仍然离开我的,因为它不会忽略string的{​​{1}}陈述列表的丑陋:)

答案 3 :(得分:3)

(abatishchev打败了我,但他的答案反正更好。但是,由于对同一问题的替代解决方案很有趣,我仍然会发布这个。)

Hackity hack hack。但是工作,如果你真的想要这样做。性能会很糟糕,因为这种技术在找到答案时不会停止 - 它总是遍历每个数字!但它会起作用:

public static int FindFirstMissing(IEnumerable<int> sequence)
{
    bool found = false;

    int agg = sequence.Aggregate((aggregate, next) => {
        if (found)
            return aggregate;

        if (next - aggregate != 1) {
            found = true;
            return aggregate + 1;
        }

        return next;
    });

    if (!found)
        throw new ArgumentException("sequence", "Contains no missing numbers.");

    return agg;
}

答案 4 :(得分:3)

string firstGap = sortedList
    .Zip(sortedList.Skip(1), (f, s) => Tuple.Create(f, s))
    .First(tup => (int.Parse(tup.Item1) + 1) != int.Parse(tup.Item2)).Item1;

应该在第一个缺口之前给你第一个项目,所以第一个缺失的元素是:

string gap = (int.Parse(firstGap) + 1).ToString();

答案 5 :(得分:1)

这有点晚了,但我认为这是一种很酷的方式:

List<int> listStringVals = (new int[] { 7, 13, 8, 12, 10, 11, 14 }).ToList();
            listStringVals.Sort();
            return listStringVals.Skip(1).Select((x, i) => x - listStringVals[i] == 1).Any(x => !x);

答案 6 :(得分:0)

为什么不只使用All,因为集合中的所有成员都需要符合标准......

实施例

someVar.All(v => someVar.Contains(v + 1) || v == someVar.Last())

然后你不必订购,而且更好。

您可以在此步骤之后进行排序,或者甚至在您需要时进行排序,但我个人只会使用已排序的集合并让它为我工作。

如果您需要在检查后获取值,然后返回检查结果或者如果您出于某种原因通过上面的多行修改以及用于存储值的列表,则可以获取值。

e.g。

someVar.All((v) => { 
    bool result = someVar.Contains(v + 1) || v == someVar.Last();
    if(!result) someList.Add(v);
    return true;
});

检查非零值列表的计数(可以订购),以表明是否满意。