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; });
检查列表的计数(可以订购)是否为非零值,以指示是否满足。
- 无法加载文件或程序集’System,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089’或其依赖项之一
- 如何从标签控件中删除虚线焦点矩形?
- 如何在运行时修改PropertyGrid(添加/删除属性和动态类型/枚举)
- 在DataGridView中选择一行并在行标题上显示箭头
- 简单的计算由于某种原因不起作用
- 将System.Data.OracleClient替换为Oracle.DataAccess(ODP.NET)
- 什么是NHibernate,我为什么要使用它?
- 动态创建IList类型的新实例
- .NET XBox Live帐户API