我有第一批数字:(1,3,5,6,23)
和第一个1到n个整数的集合集合
(3), (6,1), (1,3,5,23,6,14,67), (2,3)
所以第二个集合有元素a,b,c和d,它们本身就是整数的集合
a=(3), b=(6,1), c=(1,3,5,23,6,14,67), d=(2,3)
所以这基本上是一个锯齿状的数组)
如何使用扩展方法语法和查询表达式语法对Linq进行对象查询 找出第一个集合中的数字组合可以在a,b,c或d或无处的集合中找到。换句话说,第二个集合中的哪些数字包含在第一个集合中。
Q1:我希望看到a=(3), b=(6,1)
被发现,因为每个集合的成员a和b c都存在于第一个集合中。
Q2:我希望看到相反的情况,我们从第二个集合开始,并尝试查找其子集合成员是否属于第一个集合。
我想了解这两种方法的优缺点。实际上,我将处理数千个集合,每个集合最多包含10个数字。
答案 0 :(得分:1)
这样的东西?
int[] firstSet = new[] { 1,3,5,6,23 };
int[][] secondSet = new[]
{
new [] { 3 },
new [] { 6, 1 },
new [] { 1,3,5,23,6,14,67 },
new [] { 2, 3}
};
// only subsets where each member matces a member of the first set
var matchinSubSets = from subset in secondSet
where subset.All(x => firstSet.Contains(x))
select subset;
至于表现,不要太担心,如果你只是要匹配成千上万的参赛作品,那么在你知道它之前就会完成计算
答案 1 :(得分:1)
你走了。试试这些:
var xs = new [] { 1, 3, 5, 6, 23, };
var yss = new []
{
new [] { 3, },
new [] { 6, 1, },
new [] { 1, 3, 5, 23, 6, 14, 67, },
new [] { 2, 3, },
};
我先回答你的第二个问题:
var q2 =
from ys in yss
where !ys.Except(xs).Any()
select ys;
var q2b = yss.Where(ys => !ys.Except(xs).Any());
这两个查询是相同的 - 除了一个在LINQ中,另一个在扩展方法语法中。编译器将为两者生成相同的代码。
问题一是噩梦 - 更难做到。
var q1 =
from z in yss.Zip(
xs.Aggregate(
yss.AsEnumerable(),
(_yss, x) => (
from ys in _yss
select ys.Except(new [] { x }).ToArray())),
(ys, _ys) => new { ys, _ys })
where !z._ys.Any()
select z.ys;
var q1b =
yss.Zip(
xs.Aggregate(
yss.AsEnumerable(),
(_yss, x) => _yss
.Select(ys =>
ys.Except(new [] { x }).ToArray())),
(ys, _ys) => new { ys, _ys })
.Where(z => !z._ys.Any())
.Select(z => z.ys);
同样在LINQ和扩展方法语法中都编译为相同的代码。
我运行了一些性能测试,“q2”查询比“q1”查询快了10倍以上。
在一次测试中,我有xs
有61个不同的元素,yss
有100,000个不同的有价值的子集合,总共有956,512个元素,“q1”查询在5,354.1毫秒内运行& “q2”在302.1毫秒内运行 - 17.7倍因子。
然而,将其降至10 {和1}的xs
。 yss
10,000& 95,641然后结果是115.3&分别为7.4毫秒。这两种方法都可能足够快。