这可能有点难以描述,但我正在构建一些统计模型,我需要Linq语法的帮助...我的类比并不完全是我正在做的事情但它是我能来的最简单的描述...... ...
我有一个"命令"输入列表...我们假设我在一个范围内有一个不确定的Int列表......这个列表可能包含1到几百万个实体......
List<int> = [1, 3, 15, 16, 4, 27, 65, 2, 99, 3, 16, 21, 72, 1, 5, 7, 2, 8... ] (range 1 - 100).
我想要推断的是&#34;所有&#34;包含特定&#34;搜索&#34;的范围设置(或子列表)实体。每个子列表必须包含&#34; all&#34;来自原始输入列表中的实体,即维护内部错误数据,并且不得更改顺序...例如,如果我想搜索&#34; all&#34;从上面的列表中包含[1,2,3,4]的范围我应该
[1, 3, 15, 16, 4, 27, 65, 2]
- 包含搜索列表联合的第一个子列表。[3, 15, 16, 4, 27, 65, 2, 99, 3, 16, 21, 72, 1]
- 下一个清单...... [4, 27, 65, 2, 99, 3, 16, 21, 72, 1]
- 下一个清单......等...... 真正关键的信息是&#34;开始和结束指数&#34;每个列表...这些数据需要存储在神经网络中用作矢量数据......使用这些数据,NN可以简单地使用索引对象来进行关键数据计算......
经过一番评估后,我意识到显然每个列表都会以搜索实体开头和结尾。这导致我从这开始......
var indicies = lc.IntListData
.Select((v, i) => new { value = v, index = i })
.Where(n => search.Contains(n.value))
.ToList();
这大大减少了我的清单,从查看数百万个值的列表到查看数以千计的匿名类型的价值和索引......现在,我认为我需要的是从&#34;标记&#34找到;,第一个&#34; n&#34;匿名类型,直到我至少有一个&#34;值&#34;在列表中......不是吗?然后根据需要简单地使用索引值的最小值和最大值......
对Linq语法的任何帮助都是最有帮助的。
答案 0 :(得分:1)
如果您愿意接受辅助函数从潜在匹配列表中创建元组,那么您可以将LINQ归结为:
var subranges = matches
.Tuples(search.Length)
.Where(t => t.Select(n => n.Value).Distinct().Count() == search.Length)
.Select(t => new { StartIndex=t.Min(n => n.Index), EndIndex=t.Max(n => n.Index) })
.Select(r => list.Skip(r.StartIndex).Take(r.EndIndex-r.StartIndex+1))
;
Tuples
方法是此答案的扩展方法的变体:https://stackoverflow.com/a/577612/209103。
public static IEnumerable<IEnumerable<T>> Tuples<T>(this IEnumerable<T> sequence, int nTuple)
{
if(nTuple <= 0) throw new ArgumentOutOfRangeException("nTuple");
for(int i = 0; i <= sequence.Count() - nTuple; i++)
for (int j = i+nTuple; j < sequence.Count(); j++)
yield return sequence.Skip(i).Take(j-i);
}
请注意Tuples
为O(n n),整个解决方案为O(n n * n),因此对于较大的数据集效果不佳。
非LINQ版本的粗略初稿:
var list = new [] { 1, 3, 15, 16, 4, 27, 65, 2, 99, 3, 16, 21, 72, 1, 5, 7, 2, 8 };
var search = new [] { 1, 2, 3, 4 };
var group = new List<int>();
var start = -1;
for (var i=0; i < list.Length; i++) {
if (search.Contains(list[i])) {
if (!group.Any()) {
start = i;
}
if (!group.Contains(list[i])) {
group.Add(list[i]);
}
if (group.Count == search.Length) {
Console.WriteLine(start+" - "+i);
group.Clear();
i = start + 1;
start = -1;
}
}
}
这使用蛮力,但可以使用您首先找到匹配索引的方法进行优化。
var list = new [] { 1, 3, 15, 16, 4, 27, 65, 2, 1, 99, 3, 16, 21, 72, 1, 5, 7, 4, 2, 8 };
var search = new [] { 1, 2, 3, 4 };
var matches = list
.Select((v,i) => new { Value=v, Index=i })
.Where(n => search.Contains(n.Value))
.ToList()
;
for (var start=0; start < matches.Count(); start++) {
var group = new List<int>();
group.Add(matches[start].Value);
foreach (var match in matches.Skip(start)) {
if (!group.Contains(match.Value)) {
group.Add(match.Value);
}
if (group.Count == search.Length) {
Console.WriteLine(matches[start].Index+" - "+match.Index);
break;
}
}
}
这两种方法都是非LINQ。我不知道如何将其转换为LINQ表达式。这显然是一个分组练习(.GroupBy
),但我看不出要分组的表达方式。