C# Create double[][] from DataTable - c#

I have a DataTable where every entry in every row and column is a double. I need to convert it to a two dimensional double[][] object. There are no column headers and the number of rows and columns can be different each time.
Is there Linq to simplify this? Can I apply Math.Round() for each value as I build my double[][] object?

I'd use this approach that is efficient and safe:
DataColumn[] doubleColumns = dt.Columns.Cast<DataColumn>()
.Where(c => c.DataType == typeof(double))
.ToArray();
double[][] result = dt.AsEnumerable()
.Select(r => doubleColumns.Select(c => r.Field<double>(c)).ToArray())
.ToArray();

Having DataTable with all columns that can be converted into double (i.e. columns can be of type float, int etc.) you can put something like this:
using System.Linq;
...
DataTable table = ...
double[][] array = table
.Rows
.OfType<DataRow>()
.Select(dataRow => dataRow
.ItemArray
.Select(item => Convert.ToDouble(item))
.ToArray())
.ToArray();
Sure, you can add some processing, say, Math.Round if required; add it after the inner Select:
...
.Select(item => Convert.ToDouble(item)) // from now on we have double
.Select(value => Math.Round(value, 2)) // Let's round the values
.ToArray())
...

Related

Merge two rows into single row based on a column using LINQ C#

I have a object list like below. I want to join every two rows into single row based on column B. It is sure that only two rows would be there for every single column B value.
Input
Output
However, I have done it and solution works. but I am looking for more better solution. I am not much happy with my solution.
My solution:
var groupByItems = items.GroupBy(x => x.ColumnB).Select(x => new MappingClass
{
ColumnA= x.FirstOrDefault().ColumnA,
ColumnB= x.FirstOrDefault().ColumnB,
ColumnC= x.Where(r=> !string.IsNullOrEmpty(r.ColumnC)).Select(r=>r.ColumnC).FirstOrDefault(),
ColumnD= x.Where(r => !string.IsNullOrEmpty(r.ColumnD)).Select(r => r.ColumnD).FirstOrDefault(),
}).ToList();
Now groupByItems object returns me two rows as expected.
You can use Key of the Groups generated by GroupBy()
Also, there's no need to use .Where() you can simply put your filter as a lambda expression in .FirstOrDefault() for ColumnC & ColumnD
var groupByItems = items.GroupBy(x => new { ColumnA = x.ColumnA, ColumnB = x.ColumnB })
.Select(x => new MappingClass
{
ColumnA = x.Key.ColumnA,
ColumnB = x.Key.ColumnB,
ColumnC = x.FirstOrDefault(m => !string.IsNullOrEmpty(m.ColumnC)).ColumnC,
ColumnD = x.FirstOrDefault(m => !string.IsNullOrEmpty(m.ColumnD)).ColumnD
})
.ToList();

How to groupby Datatable by a column and sum numeric columns

I am trying to groupby a datatable by a column and sum a numeric field, but I couldnt be able to do the sum. Here is my code that groupby the datatable.
DataTable dt_grouped_by = dt_data.AsEnumerable()
.GroupBy(r => new { LOCNR = r["LOCNR"], DEPTNR = r["DEPTNR"] })
.Select(g => g.OrderBy(r => r["CODE"]).First())
.CopyToDataTable();
I have columns called quantity_received and damage_received. I need to sum those 2 columns. How can I sum them in the above code?
You have a grouping, which implements IEnumerable<DataRow>. So within that grouping you can use all LINQ extension method, like Sum():
DataTable dt_grouped_by = dt_data.AsEnumerable()
.GroupBy(r => new
{
LOCNR = r.Field<int>("LOCNR"),
DEPTNR = r.Field<int>("DEPTNR")
})
.Select(g => new
{
Code = g.First().Field<string>("CODE"),
SumQr = g.Sum(x => x.Field<int>("quantity_received"))
SumDr = g.Sum(x => x.Field<int>("damage_received"))
})
.OrderBy(x => x.Code)
.CopyToDataTable();
As you see, I prefer the Field() extension method to the row indexer row["x"], because it is strong typed. Of course I have to guess the actual data types. I also removedFirst(), because you can't convert one DataRow to a DataTable.

DataTable Rows to single Row Using LINQ

I have a single column with multiple rows in a DataTable, I want them In a single row, and dont want to loop through each row of data table,
Here is Sample Data Table
Results
-------
Clinet1
Clinet2
Clinet3
Clinet4
I want to get a string like
Clinet1,Clinet2,Clinet3,Clinet4 but using LINQ without for loop.
I tried code below but its not working for me
string Details = myDataTable.Rows
.Cast<DataRow>()
.Where(x => x["Results"].ToString();
Using LINQ:
string Details = myDataTable.Rows.Cast<DataRow>()
.Where(x => x["Results"] == UserName)
.Select(i => i.ToString()).Aggregate((i, j) => i + "," + j)
Use String.join for this.
string Details = String.join(",", myDataTable.Rows
.Cast<DataRow>()
.Where(x => x["Results"] == UserName).ToArray());
You can use AsEnumerable to return an IEnumerable<T> object, where the generic parameter T is DataRow and String.Join to join rows into a string like this;
string rows = string
.Join(",", myDataTable.AsEnumerable()
.Select(x => x["Results"]));

Use LINQ to find duplicated rows (with list of specified columns)

I use the code below to get the duplicated rows for 3 columns: String, Date, Money.
I wonder if there is any general method that I can input a dynamic List of column name in this LINQ to find duplicated rows?
DataTable allDuplicates = dt.AsEnumerable()
.GroupBy(dr => new
{
Field1 = dr.Field<object>("String"),
Field2 = dr.Field<object>("Date"),
Field3 = dr.Field<object>("Money"),
})
.Where(g => g.Count() > 1)
.SelectMany(g => g)
.ToList().CopyToDataTable();
}
How about with a custom ArrayEqualityComparer<T> type (such as the one listed here):
string[] colsToConsider = ...
var allDuplicates = dt.AsEnumerable()
.GroupBy(dr => colsToConsider.Select(dr.Field<object>)
.ToArray(),
new ArrayEqualityComparer<object>())
.Where(g => g.Count() > 1)
.SelectMany(g => g)
.CopyToDataTable();
You can also consider using a Dictionary<TKey, TValue> (and an associated dictionary-comparer) if you find the implicit use of array indices here hackish.
while execute above code.
The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly

Querying A Datable Using Linq Returning Distinct Values

I am attempting to get distinct values from a datatable column. here is my code..
var sourceItems = ds.Tables[0].AsEnumerable()
.GroupBy(x => x.Field<string>("Source").ToString())
.Select(x => x.First());
ddlSource.DataSource = sourceItems;
ddlSource.DataBind();
This code is returning 4 rows of System.Data.DataRow as the values. I need the actual values stored in the rows not the row type. Also is this code a proper way to grab only distinct values in the column?
I would do something like this:
var sourceItems = ds.Tables[0].AsEnumerable()
.Select(x => x.Field<string>("Source"))
.Distinct()
.ToList();
Note that .ToList() can be skipped, but of course it depends on what the DataSource property of the ddlSource object is able to accept. If It's a winforms control I suspect ToList is necessary.
Your code does basically the same as this one, but you must change the last Select into Select(x => x.Key) to select the values that are used to group the rows, and not the first row.
Also your code has more overhead than using Distinct, since GroupBy creates subgroups of the original collection.
Why don't you use the .Distinct extension method?
ds.Tables[0].AsEnumerable()
.Select(x => x.Field<string>("Source").ToString())
.Distinct()
.FirstOrDefault();
How about
var sourceItems = ds.Tables[0].AsEnumerable()
.Select(x => x.Field<string>("Source"))
.Distinct()
.ToList();
ddlSource.DataSource = sourceItems;
ddlSource.DataBind();
(You don't need to call .ToString() on a string, so I've removed that.)

Categories