C# 在linq中执行Join
在linQ中执行连接? var a=新列表{1,2,3,1};C# 在linq中执行Join,c#,linq,C#,Linq,在linQ中执行连接? var a=新列表{1,2,3,1}; 重复变量=a.GroupByx=>x.Anyb=>b.Count>1 以下是我如何理解您的问题。您有一个名为“表”的类,该类有一个名为“X”的列标签属性列表,以及一个名为“Y”的列表属性,该属性表示数据行 class table { public List<string> X { get; set; } // headers public List<List<object>> Y
重复变量=a.GroupByx=>x.Anyb=>b.Count>1 以下是我如何理解您的问题。您有一个名为“表”的类,该类有一个名为“X”的列标签属性列表,以及一个名为“Y”的列表属性,该属性表示数据行
class table {
public List<string> X { get; set; } // headers
public List<List<object>> Y { get; set; } // rows
}
创建IEqualityComparer以比较联接列:
var jec = new IEnumerableSequenceEqualityComparer<object>();
通过构建新的标题和行列表,将中间查询转换为表对象:
var ans = new table {
X = t1.X.Concat(Enumerable.Range(0, t2.X.Count)
.Where(n => t2wantedIndices.Contains(n))
.Select(n => t2.X[n]))
.ToList(),
Y = t3r.ToList()
};
注意:t3r查询中的GroupJoin操作为第二个参数创建了一个查找,在本例中是t2.Y参数,它使用基于hashcode的O1查找,因此不使用LINQ不会获得太多效率。如果在每个对象中做了数百万行,您可能需要考虑在过程代码中重写整个内容,以获得每行几毫秒。
以下是IEnumerableSequenceEqualityComparer定义:
public class IEnumerableSequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>> {
public bool Equals(IEnumerable<T> x, IEnumerable<T> y) =>
Object.ReferenceEquals(x, y) || (x != null && y != null && (x.SequenceEqual(y)));
public int GetHashCode(IEnumerable<T> obj) {
// Will not throw an OverflowException
unchecked {
return obj.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
}
}
}
您能为结构类型显示实际的C代码而不是伪代码吗?不,您可以使用LINQ而不转换数据。另外,根据哪个表有数百万行,最好对数据进行索引,那么a列和c列中的值是否每行唯一?a列和c列总是行的第一个位置吗?另外,您希望得到什么样的c类型的结果?另一个表结构?还有,为什么表1在示例中没有a字段?我不认为代码会编译…类和结构有一些重要的区别-你能更新你的问题使其准确吗?如果有重复的A或c条目,你希望答案包含什么?匹配的叉积?每个a值的第一个匹配c?还有别的吗?@user7112196应该是1:1。如果您想要动态查询条件,那么您将讨论一个更复杂的问题。用户是如何提供查询字符串的?@user7112196您误解了。查询条件提供了什么样的C类型和格式?对不起,我还是不明白。查询的条件只是表示要比较的列名的字符串。如果我仍然不理解,您能给出一个您想知道的示例吗?示例:要匹配的列名将是列表,每个表一个,两个表中需要匹配的索引相同,或者列名将以冒号分隔table1名称和table2名称,以逗号分隔每个列对,等等。使用您提供的解决方案,我能够在1个结果表中用左连接连接2个表。当我想显示表1的结果,而只显示表2结果的某一列时,解决方案是什么?我需要修改select方法,如select new{COLUMNAMEA=t2r[idexOfColumnNameA],COLUMNAMEB=t2r[indexOfColumnNameB]..}。ToList?
var t2wanted = new List<string> { "d", "e", "f" };
var t2wantedIndices = t2.X.Select((x, n) => (x, n)).Where(xn =>
var t3r = t1.Y.GroupJoin(t2.Y,
t1r => t1JoinIndices.Select(n1 => t1r[n1]),
t2r => t2JoinIndices.Select(n2 => t2r[n2]),
(t1r, t2rg) => (t1r,t2rg),
jec)
.SelectMany(t1rt2rg => t1rt2rg.t2rg.DefaultIfEmpty()
.Select(t2r => t1rt2rg.t1r.Concat(Enumerable.Range(0, t2.X.Count)
.Where(n => t2wantedIndices.Contains(n))
.Select(n => t2r?[n]))
.ToList()));
var ans = new table {
X = t1.X.Concat(Enumerable.Range(0, t2.X.Count)
.Where(n => t2wantedIndices.Contains(n))
.Select(n => t2.X[n]))
.ToList(),
Y = t3r.ToList()
};
public class IEnumerableSequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>> {
public bool Equals(IEnumerable<T> x, IEnumerable<T> y) =>
Object.ReferenceEquals(x, y) || (x != null && y != null && (x.SequenceEqual(y)));
public int GetHashCode(IEnumerable<T> obj) {
// Will not throw an OverflowException
unchecked {
return obj.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
}
}
}