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

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

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 

 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)); 

(注意这个问题)

然后

 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(); 

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

 List listStringVals = (new int[] { 7, 13, 8, 12, 10, 11, 14 }).ToList(); List SortedList = listStringVals.OrderBy(c => c).ToList(); List Gaps = Enumerable.Range(SortedList.First(), SortedList.Last() - SortedList.First() + 1) .Except(SortedList).ToList(); 
 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的答案,固定范围的生成。 仍然离开我的,因为它不会忽略int s的string表示列表的丑陋:)

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

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

 public static int FindFirstMissing(IEnumerable 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; } 
 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(); 

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

 List 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); 

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

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

然后你不必订购,它更好。

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

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

例如

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

检查列表的计数(可以订购)是否为非零值,以指示是否满足。