C# Linq Query for compare two tables - c#

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();

Related

C#: Count occurrences of a string in a list which is in another list using LINQ?

I am trying to count occurrences of a string in dynamically added lists in a main list. This is the main list:
public static List<string>[] tables = new List<string>[30];
This is how I add items to it:
public static int takenTablesDayTotal;
public static void AddProductToTable()
{
int tableNum = int.Parse(Console.ReadLine());
if (tableNum < 1 || tableNum > 30) { throw new Exception(); }
choiceName = Console.ReadLine();
if (tables[tableNum] is null)
{
tables[tableNum] = new List<string>();
takenTablesDayTotal++;
}
tables[tableNum].Add(choiceName);
}
And this is how I have tried to do the counting, but it doesn't seem to work right for some reason (starts at 1 and stops counting there when the required string is detected)
salesProductDayTotal = tables.Where(s => s != null && s.Contains("string")).Count();
I'm not sure how to make this work, so any help will be appreciated!
Thanks in advance!
You can use SelectMany to deliminate the two-nest structure.
Then use Count to get what you want.
For example - count the daily apple sales number
List<string>[] tables = new List<string>[30];
tables[0] = new List<string>{
"Apple", "Banana", "Cherry"
};
tables[1] = new List<string>{
"Peach", "Apple", "Watermelon"
};
tables[2] = new List<string>{
"Mango", "Grape", "Apple"
};
//the daily sales count of Apple.
var dailyAppleSalesCount = tables.Where(x => x != null)
.SelectMany(s => s).Count(x => x == "Apple");
You can use SelectMany to flatten the List<List<string>> into one large List<string>, and then count the products.
You don't need to use Contains, IMO ("Chicken soup" is probably a different product on the menu that "Spicy Chicken Soup"), so it simplifies the condition a bit.
salesProductDayTotal = tables
.Where(t => t != null)
.SelectMany(products => products)
.Count(p => p == "string")
You could also use a GroupBy clause to do this calculations on all the products at once.
Explanation of your problem:
You were using the Count on the outer list, the list of tables. So you had just "one match" for each table that contains the product at least once.

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"]);
}

Query rows that the datatable field contain any item in the list<string>

i'm new in LINQ.
I wanna query all rows that the description column string (example value "i am feeling lucky today.") contains/match any item in a List<string> lst.
Example the list items contain {"lucky", "bad", "ok" }.
I would like to achieve by using linq only, but I am confuse are below methods correct??
thanks.
Option 1:
var item =
from a in datatbl.AsEnumerable()
from b in lst
where a.Field<string>("description").contains(b)
select a;
Option 2:
var item =
from a in datatbl.AsEnumerable()
where lst.Any(x=> a.Field<string>("description").Contains(x))
select a;
Both of your options should work (change contains to Contains). But if you want to be case-insensitive, you will need to use a ToUpper or something.
For example, this code provides a "test jig" and handles case insensitivity.
DataTable datatbl = new DataTable();
datatbl.Columns.Add(new DataColumn("description",typeof(string)));
// add simple test rows
datatbl.Rows.Add("I'm feeling lucky today.");
datatbl.Rows.Add("I'm feeling bad today.");
datatbl.Rows.Add("I'm feeling good today.");
// more test rows here...
List<string> lst = new List<string>(new string[] { "Lucky", "bad", "ok" });
var item =
from a in datatbl.AsEnumerable()
from b in lst
where a.Field<string>("description").ToUpper().Contains(b.ToUpper())
select a;
var item2 =
from a in datatbl.AsEnumerable()
where lst.Any(x => a.Field<string>("description").ToUpper().Contains(x.ToUpper()))
select a;
Found out that if one row value is I'm not feeling Lucky, bad or ok today. with Linq below:
List<string> lst = new List<string>(new string[] { "Lucky", "bad", "ok" });
var item = from a in datatbl.AsEnumerable()
from b in lst
where a.Field<string>("description").ToUpper().Contains(b.ToUpper())
select a;
the result will return me 3 duplicated records of the same row, seem like it's not distinct by default. is this the case of above linq??
To get the distinct rows, i need to revise to:
List<string> lst = new List<string>(new string[] { "Lucky", "bad", "ok" });
var item = (from a in datatbl.AsEnumerable()
from b in lst
where a.Field<string>("description").ToUpper().Contains(b.ToUpper())
select a).Distinct();

Getting Only The Top Row From Each Group

I have some code that groups a table by "Value1" and some loops that add the top row of each group to a list. This is a pretty ugly way to do this, and I was wondering if I could replace one of the foreach loops with a couple more lines in my LINQ query? Problem is, I don't have the foggiest idea how to do this.
var Result =
from a in DB.Table1
group new {Values = a} by a.Value1 into c
select new {everything = c};
foreach (var Row in Result)
{
foreach (var RowAll in Row.Everything)
{
List.Add(new List<string>() {RowAll.Value1, RowAll.Value2})
break;
}
}
Use Enumerable.First:
var List =
(from Row in Result
let RowAll = row.Everything.First()
select new List<string>() {RowAll.Value1, RowAll.Value2}
).ToList();
Or, combined with your original query:
var List =
(from a in DB.Table1
group a by a.Value1 into c
select new List<string>() {c.Key, c.First().Value2}
).ToList();
Use FirstOrDefault:
var query = from row in result
let rowAll = row.Everything.FirstOrDefault()
where rowAll != null
select new List<string> {rowAll.Value1, rowAll.Value2};
var list = query.ToList();
Rereading you first query I realised you are grouping on a property of 'a' so there should be no empty groupings. First() should be safe as in the other posters example.

Linq - using not "IN" operator to select non duplicated lines from a text file

I am using Linq to select and process lines from a text file. My txtfile is two columns delimitted by the pipe character "|". The File contains the following:
HAbbe|11
GABBOT|22
DABDA|33
RAchant|44
RADA|55
DABDA|66
You will notice that line 3 and line 6 have a duplicated ID(Column 1). I want to use linq to initially read the posted txt file find the duplicate (and report on it) and then I would like to select from ling query only the lines that are not duplicated. The following is what I have :
StreamReader srReader = new StreamReader(fUpload.PostedFile.InputStream);
var query1 =
from line in srReader.Lines()
let items = line.Split('|')
select new UploadVars()
{
ID = items[0],
Number = items[1]
};
var GroupedQuery = from line in query1
group line by line.ID into grouped
where grouped.Count() > 1
select new {
ID = grouped.Key,
MCount = grouped.Count()
};
StringBuilder sb = new StringBuilder();
foreach (var item in GroupedQuery)
{
sb.AppendFormat("The following external ID's occur more than once and have not been processed:<br> {0}. Duplicated {1} times.", item.ID, item.MCount);
}
This is all ok and giving me the correct results. I am now looking to select all the lines except the 2 duplicated lines from the text file. I have composed the following linq statement but for some reason I am having no luck:
//lets start at the beginnnig of the the posted filestream
fUpload.PostedFile.InputStream.Position = 0;
srReader = new StreamReader(fUpload.PostedFile.InputStream);
var query2 = from line in srReader.Lines()
let items = line.Split('|')
select new UploadVars()
{
ID = items[0],
Number = items[1]
};
var qryNoDupedMems = from Memb in query2
where !(from duped in GroupedQuery
select duped.ID)
.Contains(Memb.ID)
select Memb;
The result of qryNoDupedMems is the complete list from the text file. Could someone explain what I'm doing wrong here...
Thanks in Advance
In a group query, the grouped variable is also an IEnumerable containing the tems in the group.
Therefore, you can write the following:
var nonDuplicates = from line in query1
group line by line.ID into grouped
where grouped.Count() == 1
select grouped.First()

Categories