Linq 如何将包含部分重复数据的多行合并为一行,但保留非重复数据?

Linq 如何将包含部分重复数据的多行合并为一行,但保留非重复数据?,linq,datatable,merge,Linq,Datatable,Merge,我得到了一个超过300K行的大数据表,其中包含40列数据,这些片段都是字符串: 感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒 ---------------------------- A01 B01 C01 DA1 EA1 FA1 GA1 HA1 A01 B01 C01 DA2 EA2 FA2 GA2 HA2 A02 B02 C02 DA3 EA3 FA

我得到了一个超过300K行的大数据表,其中包含40列数据,这些片段都是字符串:

感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒感冒 ---------------------------- A01 B01 C01 DA1 EA1 FA1 GA1 HA1 A01 B01 C01 DA2 EA2 FA2 GA2 HA2 A02 B02 C02 DA3 EA3 FA3 GA3 HA3 A02 B02 C02 DA4 EA4 FA4 GA4 HA4 A03 B03 C03 DA5 EA5 FA5 GA5 HA5 A04 B04 C04 DA6 EA6 FA6 GA6 HA6

有部分数据重复,我想合并重复的数据,使用colA+ColB+ColC作为key和keep ColE ColF,使用第一行作为其他列。预期结果如下:

可乐colB colC ColD1 col1 colF1 colG1 ColD2 colF2 colG2 ColH ------------------------ A01 B01 C01 DA1 EA1 FA1 GA1 DA2 EA2 FA2 GA2 HA1 A02 B02 C02 DA3 EA3 FA3 GA3 DA4 EA4 FA4 GA4 HA3 A03 B03 C03 DA5 EA5 FA5 GA5空HA5 A04 B04 C04 DA6 EA6 FA6 GA6空HA6

它有点像pivot,但有一些不同,我尝试将T-SQL或LINQ与C结合使用,但不知道如何使用,请帮助,非常感谢。

注意,这不是一个通用的解决方案,但在给定的示例中可以使用

List<string[]> input = new List<string[]>()
{
    new string[] {"A01","B01","CA1","DA1"},
    new string[] {"A01","B01","CA2","DA2"},
    new string[] {"A02","B02","CA3","DA3"},
    new string[] {"A02","B02","CA4","DA4"},
    new string[] {"A03","B03","CA5","DA5"},
    new string[] {"A04","B04","CA6","DA6"},
};

var grouped = input.GroupBy(x => new { key1 = x[0], key2 = x[1] }, (keys, group) => new
{
    Key1 = keys.key1,
    Key2 = keys.key2,
    // skip(2) to prevent the keys to be added in the list
    Result = group.SelectMany(x => x.Skip(2)).ToList()
});
输出:

{Key1=A01,Key2=B01,Result=[CA1,DA1,CA2,DA2]}

{Key1=>A02,Key2=B02,Result=[CA3,DA3,CA4,DA4]}

{Key1=A03,Key2=B03,Result=[CA5,DA5]}

{Key1=A04,Key2=B04,Result=[CA6,DA6]}


听起来像是一份工作

依赖于您提供的输入记录

var input = new DataTable();
input.Columns.Add("ColA");
input.Columns.Add("ColB");
input.Columns.Add("ColC");
input.Columns.Add("ColD");
input.Rows.Add("A01", "B01", "CA1", "DA1");
input.Rows.Add("A01", "B01", "CA2", "DA2");
input.Rows.Add("A02", "B02", "CA3", "DA3");
input.Rows.Add("A02", "B02", "CA4", "DA4");
input.Rows.Add("A03", "B03", "CA5", "DA5");
input.Rows.Add("A04", "B04", "CA6", "DA6");
您可以将记录转换为动态可扩展对象

public IDictionary<string, Object> Map(DataRow row)
{
    var columns = row.Table.Columns;
    var result = new ExpandoObject() as IDictionary<string, Object>;
    for (var index = 0; index < row.ItemArray.Count(); index++)
    {
        result.Add($"{columns[index]}", row[index]);
    }
    return result;
}
然后一点逻辑意味着按标记元素对输入进行分组,并在需要的地方进行扩展

var seed = new List<IDictionary<string, Object>>();
var output = input
    .AsEnumerable()
    .Select(Map)
    .Aggregate(seed, (results, current)=>
    {
        // Check if the current values match any of the first element in the results
        var query = from result in results
                    let marker = result
                        .Select(p => p.Value)
                        .FirstOrDefault()
                    where current.Values.Contains(marker)
                    select result;

        var found = query.SingleOrDefault();
        if (found == null)
        {
            // None were found then simply append the current values
            results.Add(current);
        }
        else
        {
            // Some were found then isolate the new ones
            var others = from value in current.Values
                         where !found.Values.Contains(value)
                         select value;

            // Append the new ones to the found result
            foreach (var value in others)
            {
                var index = found.Values.Count;
                found.Add($"Col{index}".ToString(), value);
            }
        }

        return results;
    });
最终的结果是这样的


查看全貌

谢谢你的帮助,我已经更新了我的问题,试图让问题更清楚,你能帮忙吗?你能更具体一点吗?这个解决方案产生了预期的结果。或者不是吗?我无法将示例中的输入替换为datatable,存在一个错误,例如无法从用法推断。尝试显式指定类型参数,我需要将转换结果的列名保留回datatable。谢谢你的帮助。你已经劫持了问题的范围,并通过编辑将其转移到了datatables:尽管如此,请查看我的更新答案,该答案使用datatable作为数据输入。谢谢你的帮助,我已经更新了我的问题,试图让问题更清楚,你能帮助我吗?