How to search list of values in DataTable? - c#

I have a DataTable with some n number of columns and array of string to search in this table.
I want to search all these strings in DataTable and store matching strings in list.
Columns in DataTable are dynamic so using below code I got list of Columns from DataTable.
But not sure how to search and get matching records using LINQ or any other technique with best feasible approach.
DataColumn[] cols = dt.Columns.Cast<DataColumn>().ToArray();

This should work:
DataColumn[] cols = dt.Columns.Cast<DataColumn>().ToArray();
var rows = dt.AsEnumerable();
List<string> foundList = searchList
.Where(s => rows.Any(r => cols.Any(c => r[c].ToString().Equals(s))))
.ToList();
But this would be more efficient:
HashSet<string> searchStrings = new HashSet<string>(searchList); // or use a HashSet<string> instead of a list in the first place
List<string> foundList = new List<string>();
foreach (DataRow row in dt.Rows)
{
IEnumerable<string> matches = cols
.Select(c => row[c].ToString())
.Where(searchStrings.Contains); // Contains is O(1) operation
foreach (string match in matches)
{
foundList.Add(match);
searchStrings.Remove(match); // Remove is O(1) operation. It has another advantage: at the end searchStrings contains only strings that were not found
}
}

Related

C# Linq Query for compare two tables

I want linq c# query to compare two tables and list unmatched record from table 1
List<MyClass> Unmatched = new List<MyClass>();
foreach (var row in Table_A)
{
if (Table_B.Count(x => x.ID == row.ID) == 0)
Unmatched.Add(row);
}
Something like that?
It will only check Unmached Table1 to Table2.
It doesn't check Table2 to Table1.
We need more details.
EDIT
The last line of code compares the elements of two lists and with ! Contains keep only the unmatched elements of the first list and added to the new Unmathced list:
List<string> table_1 = new List<string>() { "panos", "mitsos", "alex", "niki" };
List<string> table_2 = new List<string>() { "panos", "mitsos", "alexandros", "maria" };
List<string> UnmatchedList= new List<string>();
UnmatchedList = table_1.Where(x => !table_2.Contains(x)).ToList();

c# Aggregate an enumerable containing a list<string> into one union list then get distinct values

I am sure the is a elegant way to do this more expressively
IEnumerable<List<string>> list = api.call();
List<string> distinct = new List<string>();
foreach (var result in list)
{
foreach (var subject in result )
{
if (!distinct.Contains(subject))
{
distinct.Add(subject);
}
}
}
How about:-
List<string> distinct = list.SelectMany(x => x).Distinct().ToList();
You can flatten the list using SelectMany and fetch distinct items.

Store values from dataset to a list

I have created a Dataset from my database icluding two columns and I want to store all the rows of the second column(containing strings) to a list. How can I do that?
Use Select?
var myStrings = myDataSet.Tables[0].AsEnumerable()
.Select(x => x.StringColumn).ToList;
You could also use a loop:
var list = new List<string>();
foreach(DataRow row in myDataSet.Tables[0].Rows)
{
list.Add((string)row["StringColumn"]);
}

FileNames in a DataTable - First Column

Is there a way to get the list of FileNames in a DataTable without using a foreach loop?
DataTable dtOutput = new DataTable();
dtOutput.Columns.Add("FileName", typeof(string));
dtOutput.Columns.Add(Col2..., typeof(decimal));
...
foreach (string file in Directory.EnumerateFiles(txtBoxReadFrom.Text, txtBoxTargetFilter.Text))
{
dtOutput.Rows.Add(Path.GetFileName(file));
}
progressBar1.Maximum = dtOutput.Rows.Count;
Linq hides the loops from you, it uses them anyway:
List<String> allFileNames = dtOutput.AsEnumerable()
.Select(r => r.Field<string>("FileName"))
.ToList();
But why do you want a list at all when you already have the table which is also an in-memory collection?
If you want to diplays these file-names in another multiline TextBox you can use:
txtBoxWriteTo.Lines = dtOutput.AsEnumerable()
.Select(r => r.Field<string>("FileName"))
.ToArray();
Convert the DataTable object to Enumerable().
Apply the select clause with the column name as field name.
Cast it to a string array.
string[] strSummCities = dtTemp1.AsEnumerable().Select(s => s.Field<string>("City")).ToArray<string>();
Hope this will help t resolve your query.
you should add a reference to System.Data.DataSetExtension in order to have the CopyToDataTable() for enumerable values, after this you can use:
DataTable dtOutput =
Directory.EnumerateFiles(txtBoxReadFrom.Text, txtBoxTargetFilter.Text).Select(r =>
{
DataRow row = dtOutput.NewRow();
row["fileName"] = r;
return row;
}).CopyToDataTable();

List<String[]> - Need suggestion as how to pull record from String[]

I have a text file that contains 1000's of rows (around 30 column each row) and need to pull desired row based on some condition.
using below code I have the collection ready from text file into List
string[] records = File.ReadAllLines(path);
List<string> listOfStr = new List<string>(records);
I need to query a particular column of each row... if that match with criteria.. I need that record...
How can I do this using linq? Or any other approach ?
You should use File.ReadLines instead which streams the lines instead of loading all into memory first. Also, you are creating two in-memory collections here:
string[] records = File.ReadAllLines(path);
List<string> listOfStr = new List<string>(records);
This is much more efficient in terms of memory consumption:
var matchingLines = File.ReadLines(path)
.Select(l => new{ Parts = l.Split(), Line = l })
.Where(x => x.Parts.ElementAtOrDefault(9) == yourSearch)
.Select(x => x.Line);
foreach (string line in matchingLines)
Console.WriteLine(line);
You haven't mentioned what delimiter separates each column, i have used white-spaces, l.Split(',') would split by comma. Enumerable.ElementAtOrDefault(9) retuns the 10th column if available, otherwise null is returned.
First split the lines into columns:
List<string[]> listOfStr = records.Select(s => s.Split('\t')).ToList();
You can use the Where method to filter on a condition.
This for example filters out all rows where the fifth column is "Hello":
List<string[]> result = listOfStr
.Where(s => s[4] == "Hello")
.ToList();
string[] records = File.ReadAllLines(path);
List<string> listOfStr = new List<string>(records);
List<string> listOfMatches = listOfStr.Where(str => str[YOUR TEST COLUMN].Equals([YOUR TEST VALUE])).ToList();
Try this if the lines are separated by comma:
int indexCol = 0; //the index of the col you want to look into
string search = string.Empty; //what you want to search in the column
string lineResult = listOfStr.FirstOfDefault(x=> x.split(",")[indexCol].Contains(search));
Other
string search = string.Empty;
foreach (string line in listOfSrt)
{
string[] inCols = line.Split("\t");
if (inCols[0].Contains(search))
{
Console.WriteLine(line);
}
}

Categories