简体   繁体   English

如何转置数据表以获取 C# 中的第二个数据表?

[英]How to transpose a datatable to get the second datatable in C#?

I am a new C# developer and I am struggling now with converting the columns in the following DataTable into rows.我是一名新的 C# 开发人员,我现在正在努力将以下 DataTable 中的列转换为行。 The current DataTable structure I have is:我拥有的当前 DataTable 结构是:

Id      Value
1       Test#1
1       Test#2
2       Car#1
2       Car#2
3       Airplane#1
3       Airplane#2

I need to convert it into the following table structure:我需要将其转换为以下表结构:

1           2           3
Test#1      Car#1       Airplane#1
Test#2      Car#2       Airplane#2

I tried to implement it using the following method I found in Google, but I am still not getting the desired result:我尝试使用我在 Google 中找到的以下方法来实现它,但我仍然没有得到想要的结果:

private DataTable GenerateTransposedTable(DataTable inputTable)
        {
            DataTable outputTable = new DataTable();

            // Add columns by looping rows

            // Header row's first column is same as in inputTable
            outputTable.Columns.Add(inputTable.Columns[0].ColumnName.ToString());

            // Header row's second column onwards, 'inputTable's first column taken
            foreach (DataRow inRow in inputTable.Rows)
            {
                string newColName = inRow[0].ToString();
                outputTable.Columns.Add(newColName);
            }

            // Add rows by looping columns      
            for (int rCount = 1; rCount <= inputTable.Columns.Count - 1; rCount++)
            {
                DataRow newRow = outputTable.NewRow();

                // First column is inputTable's Header row's second column
                newRow[0] = inputTable.Columns[rCount].ColumnName.ToString();
                for (int cCount = 0; cCount <= inputTable.Rows.Count - 1; cCount++)
                {
                    string colValue = inputTable.Rows[cCount][rCount].ToString();
                    newRow[cCount + 1] = colValue;
                }
                outputTable.Rows.Add(newRow);
            }

            return outputTable;
        }

Could you please tell me how I can transpose the first DataTable into the second one?您能否告诉我如何将第一个 DataTable 转换为第二个?

Using an extension method, you can pivot the original DataTable by creating the implied row number column that groups the answer rows together:使用扩展方法,您可以通过创建将答案行组合在一起的隐含行号列来 pivot 原始DataTable

public static class DataTableExt {
    // Transpose a DataTable to a new DataTable
    // over field creates new column names
    // value field is value for new columns
    // Original datatable must be sorted in OverColFieldName then row number order
    public static DataTable Transpose(this DataTable dt, string OverColFieldName, string WithValueFieldName) {
        var res = new DataTable();
        if (dt.Rows.Count > 0) {
            var ColCount = dt.AsEnumerable().Select(r => r.Field<int>(OverColFieldName)).Distinct().Count();
            var rowCount = dt.Rows.Count / ColCount;
            var rowNumbers = Enumerable.Range(0, rowCount*ColCount).Select(rn => rn % rowCount +1);

            var rowGroups = dt.AsEnumerable()
                              .Zip(rowNumbers, (r, rn) => new { Row = r, RowNum = rn }) // associate an answer Row Number with each row
                              .GroupBy(rrn => rrn.RowNum, rrn => new { Over = rrn.Row[OverColFieldName].ToString(), With = rrn.Row[WithValueFieldName] }); // group the columns for each answer row together

            var valueDataType = dt.Columns[WithValueFieldName].DataType;
            var colNames = rowGroups.SelectMany(rg => rg.Select(r => r.Over)).Distinct().OrderBy(n => n);
            foreach (var n in colNames)
                res.Columns.Add(n, valueDataType);

            foreach (var rowGroup in rowGroups) {
                var newr = res.NewRow();

                foreach (var r in rowGroup)
                    newr[r.Over] = r.With;
                res.Rows.Add(newr);
            }
        }
        return res;
    }
}

And you can use it by passing in the Column Names for the source of the new columns and the values to be placed in each column:您可以通过传入新列源的列名和要放置在每列中的值来使用它:

var ans = dt.Transpose("Id", "Value");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM