I have a datatable which contains only one column and all items are strings. How can I convert this to a List<string> using LINQ for example?
I Tried:
DataRow[] rows = dtusers.Select();
var qq = from RowCollection in rows
select new { UserCode = LibStatic.ToStr(RowCollection["UserCode"]) };
List<string> users = new List<string>();
users = qq.Cast<string>().ToList();
There is the easyway which always works:
foreach (DataRow dr in dtusers.Rows)
{
users.Add(dr[0].ToString());
}
You can use LINQ query to do that.
List<string> list = dtusers.AsEnumerable()
.Select(r=> r.Field<string>("UserCode"))
.ToList();
You can try this code,
List<string> list = dt.Rows.OfType<DataRow>().Select(dr => (string)dr["ColumnName"]).ToList();
Related
I have a DataTable like this
ColA ColB
1 OneThree
2 FourTwo
3 EightNine
4 ThreeEightFive
5 SevenNine
and the substrings are in another array ("Two","Eight", "Three")
How do I filter the DataTable using ColB and get the rows which contains any one of the substrings in the array? Array might have n number of substrings.
Is there a possible way using Linq without looping thru each array element and checking the colB using CONTAINS keyword?
This will return all ColB values that contain values from your list.
var dt = // your datatable
var list = new List<string>{ "Two", "Eight", "Three" };
var matches = dt.AsEnumerable()
.Where(dr => list.Any(l => dr.Field<string>("ColB").Contains(l)))
.Select(r => r.Field<string>("ColB"))
.ToList();
Please note that Linq still performs loops behind the scenes. This may not be very efficient (due to the Where/Any), especially on large data sets.
If you want to return a DataTable use CopyToDataTable():
var matches = dt.AsEnumerable()
.Where(dr => list.Any(l => dr.Field<string>("ColB").Contains(l)))
.CopyToDataTable();
you can use LINQ as shown below to query datatable
DataTable dt = new DataTable();
dt.Columns.Add("ColA", typeof(int));
dt.Columns.Add("ColB", typeof(string));
dt.AcceptChanges();
var r1 = dt.NewRow();
r1["ColA"] = 1;
r1["ColB"] = "OneThree";
dt.Rows.Add(r1);
var r2 = dt.NewRow();
r2["ColA"] = 2;
r2["ColB"] = "FourTwo";
dt.Rows.Add(r2);
var r3 = dt.NewRow();
r3["ColA"] = 3;
r3["ColB"] = "EightNine";
dt.Rows.Add(r3);
var r4 = dt.NewRow();
r4["ColA"] = 4;
r4["ColB"] = "ThreeEightFive";
dt.Rows.Add(r4);
var r5 = dt.NewRow();
r5["ColA"] = 5;
r5["ColB"] = "SevenNine";
dt.Rows.Add(r5);
dt.AcceptChanges();
var subArray = new string[3] { "Two", "Eight", "Three" };
var query = from r in dt.AsEnumerable()
where subArray.Any(s=> r.Field<string>("ColB").IndexOf(s,StringComparison.InvariantCultureIgnoreCase)>-1)
select r.Field<string>("ColB");
foreach (var item in query)
{
Console.WriteLine(item);
}
If I well understand you need something like this.
Change MyDataTable with your filled DataTable and work on code following your necessities.
Dim containsMyWords As Func(Of String, Boolean) = Function(entryS As String)
Dim myWords() As String = {"r1", "r2", "r3", "r4", "r5", "r6"}
If myWords.Contains(entryS) Then Return True
Return False
End Function
Dim listRows = From dtR As DataRow In MyDataTable.AsEnumerable
Where containsMyWords(CType(dtR.Item("ColB"), String))
For Each mRow In listRows
Console.WriteLine(Join(mRow.ItemArray, "~"))
Next
I have a datatable where I need to take n number of columns. For ex: From the below datatable I need to take first 10 columns alone with data and put it in another datatable.
Code:
DataTable dtRecord = DAL.GetRecords();
I tried this and this doesn't take the required column.
var selectColumns = dtRecord .Columns.Cast<System.Data.DataColumn>().Take(10);
You can also use this
private DataTable GetNColumnsFromDataTable(DataTable tblSource, int outputCols)
{
DataTable columnOutput = tblSource.Copy();
if (outputCols > 0 && outputCols < tblSource.Columns.Count)
{
while (outputCols < columnOutput.Columns.Count)
{
columnOutput.Columns.RemoveAt(columnOutput.Columns.Count - 1);
}
}
return columnOutput;
}
You can do it like this:
var selectColumns = dtRecord.Columns.Cast<DataColumn>().Take(10);
var dtResult = new DataTable();
foreach (var column in selectColumns)
dtResult.Columns.Add(column.ColumnName);
foreach (DataRow row in dtRecord.Rows)
dtResult.Rows.Add(row.ItemArray.Take(10).ToArray());
Perhaps you should create a column of the same type and with the same expression:
dtResult.Columns.Add(column.ColumnName, column.DataType, column.Expression);
To copy from one DataTable to another, you can extract the columns of interest
var moveCols = dtRecord.Columns.Cast<DataColumn>().Take(10).Select(c => c.ColumnName).ToArray();
Then you must create new DataColumns in a new table, then create new DataRows in the new table:
var newTable = new DataTable();
foreach (var c in moveCols)
newTable.Columns.Add(c);
foreach (var r in dtRecord.AsEnumerable())
newTable.Rows.Add(moveCols.Select(c => r[c]).ToArray());
Which you can make an extension method on DataTable:
public static DataTable Slice(this DataTable dt, params string[] colnames) {
var newTable = new DataTable();
foreach (var c in colnames)
newTable.Columns.Add(c, dt.Columns[c].DataType);
foreach (var r in dt.AsEnumerable())
newTable.Rows.Add(colnames.Select(c => r[c]).ToArray());
return newTable;
}
Now you can call
var newTable = dtRecord.Slice(moveCols);
With a nice extension method, you can convert from Dictionarys to a DataTable dynamically:
var newTable = dtRecord.AsEnumerable().Select(r => moveCols.ToDictionary(c => c, c => r[c])).AsDataTable();
I have some for converting ExpandoObject and anonymous objects as well, as well as an extension to convert those to anonymous objects dynamically. Here is the code for Dictionarys to DataTable:
public static DataTable AsDataTable(this IEnumerable<IDictionary<string, object>> rows) {
var dt = new DataTable();
if (rows.Count() > 0) {
foreach (var kv in rows.First())
dt.Columns.Add(kv.Key, kv.Value.GetType());
foreach (var r in rows)
dt.Rows.Add(r.Values.ToArray());
}
return dt;
}
public static DataTable AsDataTable(this IEnumerable<Dictionary<string, object>> rows) => ((IEnumerable<IDictionary<string, object>>)rows).AsDataTable();
Get 10 columns:
var tbl = new System.Data.DataTable();
var cols = tbl.Columns.Cast<System.Data.DataColumn>().Take(10);
// if you wish to get first 10 columns...
If you want to get the data, then you have to loop through the columns to get the data.
var data = cols.SelectMany(x => tbl.Rows.Cast().Take(10).Select(y => y[x]));
of course, this will dump all the data into an ienumerable, if you want to use strong typed object or a list of one dimensional array, believe it's fairly simple, for example:
var data2 = cols.Select(x => tbl.Rows.Cast().Take(10).Select(y => y[x]).ToArray());
I have two arrays converted from datatables.
I need to join the two arrays on a condition and then databind the final results to a ListView.
The first array has only one column, and the second has several. I need to join them where column txtItemA on searchResults is equal to txtItemNumber on queryResults column.
I'm not sure even if I'm on the right track. Visual Studio is showing a redline under searchresults in this line....
var showResults = from a in searchResults
My code...
ArrayList searchResults = new ArrayList();
foreach (DataRow dataRow in dt2.Rows)
searchResults.Add(string.Join(";", dataRow.ItemArray.Select(item => item.ToString())));
ArrayList queryResults = new ArrayList();
foreach (DataRow dataRow in dt2.Rows)
queryResults.Add(string.Join(";", dataRow.ItemArray.Select(item => item.ToString())));
var showResults = from a in searchResults
join b in queryResults on b.txtItemNumber equals a.txtItemA
select new
{
newseries = searchResults.newseries,
series = searchResults.series
};
ListView1.DataSource = showResults.ToArray();
ListView1.DataBind();
I tried using this code from Gilad Green...
List<string> searchResults = new List<string>();
foreach (DataRow dataRow in dt2.Rows)
searchResults.Add(string.Join(";", dataRow.ItemArray.Select(item => item.ToString())));
List<string> queryResults = new List<string>();
foreach (DataRow dataRow in dt2.Rows)
queryResults.Add(string.Join(";", dataRow.ItemArray.Select(item => item.ToString())));
var showResults = searchResults.Where(item => queryResults.Contains(item.txtItemA)
.Select(item => new {
newseries = item.newseries,
series = item.series
}));
I still cant get this to work..
Errors on item in the line.....Select(item => new {
parameter or local variable cannot have the same name as a method type parameter
and txtItemA
string does contain a definition for txtItemA and no extension method....
Try the following, It uses standard DataRows and I'm guessing the field names based on your sample code.
DataTable dt2 = new DataTable();
var showResults = dt2.Rows.Cast<DataRow>().Join(dt2.Rows.Cast<DataRow>(), a => a.Field<string>("txtItemNumber"), b => b.Field<string>("txtItemA"), (a, b) => new
{
newseries = a.Field<string>("newseries"),
series = a.Field<string>("series")
});
ListView1.DataSource = showResults.ToArray();
ListView1.DataBind();
I have DataTable object (OutputDT1), I want to use LINQ to group by column ConfirmedBy, then convert it back to a DataTable object which has only two columns ConfirmBy and Count.
var result = from row in OutputDT1.AsEnumerable()
group row by new
{
ConfirmedBy = row.Field<string>("ConfirmedBy")
}
into grp
select new
{
ConfirmedBy = grp.Key.ConfirmedBy,
Count = grp.Count(),
};
A simple way would be:
DataTable dt = new DataTable();
foreach(var item in result)
{
dt.Rows.Add(item.ConfirmedBy, item.count);
}
Using the solution from How to: Implement CopyToDataTable<T> Where the Generic Type T Is Not a DataRow
we can write:
var result = (from row in OutputDT1.AsEnumerable()
group row by row.Field<string>("ConfirmedBy") into grp
select new
{
ConfirmedBy = grp.Key,
Count = grp.Count(),
}).CopyToDataTable();
I have a list<string> and a DataSet. I need to write a Linq query to get the values from dataset or datatable to check if the values are present in List<string>. Please help me in writing the query to get datas from dataset or datatable
i will use foreach after getting the values to check whether the data is present in list<string>
EDIT:
DataSet dsDuplicate = (DataSet) Session["EventDescription"];
DataTable dt = dsDuplicate.Tables[0];
string cellValue = string.Empty;
for (int rowCount = 0; rowCount < gvEventMechanic.Rows.Count; rowCount++)
{
TextBox textBoxId = (TextBox)gvEventMechanic.Rows[rowCount].Cells[2].FindControl("txtId");
lstStringId.Add(textBoxId.Text);
}
List<string> list = ...
DataTable table = ...
var items = new HashSet<string>(list);
var results = from row in table.AsEnumerable()
where items.Contains(row.Field<string>("YourColumnName"))
select row;
foreach (var matchingRow in results)
{
// do whatever
}
Note: If you need the results to be in the form of another DataTable or DataView (such as for databinding), there are methods for that.
var output = results.CopyToDataTable(); // or
var output = results.AsDataView();