i have a simple query in Linq which gets the characters group by word length, below is the code
string sentence = "This is sample linq query";
string[] words = sentence.Split(' ');
var query = from word in words
group word by word.Length into gr
orderby gr.Key ascending
select new { Length = gr.Key, Words = gr };
foreach (var obj in query)
{
Console.WriteLine("Word of Length: {0}", obj.Length);
foreach (string word in obj.Words)
{
Console.WriteLine("{0}", word);
}
Console.WriteLine();
}
it works properly, now i want to convert this into the windows form application by placing the above records into DataGridView, so i implemented like below.
string sentence = "This is sample linq query";
string[] words = sentence.Split(' ');
var query = from word in words
group word by word.Length into gr
orderby gr.Key ascending
select new { Length = gr.Key, Words = gr };
dataGridView1.DataSource = query.ToList();
but here i just gets first coluumn (Length) in the DataGridView and not Words column, is there anything else i need to do to get both columns.
In your case the words-part of the grouping consists of an IGrouping - which cannot be displayed by the datagrid. Try concatenating the words as follows:
var query = from word in words
group word by word.Length into gr
orderby gr.Key ascending
select new { Length = gr.Key, Words = gr.Aggregate((left, right)=>string.Format("{0}, {1}", left, right)) };
Then you will see two columns in the grid, one with the length, the other with the now again concatenated words of that length.
Related
I am curious what the x is for in a a linq group by clause: group x by ...
The x can be replaced by an 1:
var query = from box in c.Boxes
join item in c.Items on box equals item.Box
group 1 by new { BoxId = box.BoxId, item.ItemType.ItemTypeId } into g
select new { g.Key.BoxId, g.Key.ItemTypeId, Count = g.Count() };
Does anybody have a sample where the x (or wathever local variable you chose in the group by ) is really of some value?
I mean
var query2 = from box in c.Boxes
group box by box.BoxId into q
select q.Key;
can be replaced by
var query2 = from box in c.Boxes
group 1 by box.BoxId into q
select q.Key;
That's the expression that determines what will go in the output of the group by clause.
You are actually not inspecting the whole output, but only the Keys, which are the same in the examples above, because the grouping is done by the same thing (box.BoxId).
However, replace the last line:
select q.Key;
with
select q;
You will notice that:
the group 1 by ... query will return an IGrouping<int, int> which will have all values set to 1
the group box by ... query will return an IGrouping<int, Box>, which will have all the boxId keys and, for each of them, the corresponding Box objects with respect to the grouping criteria.
In group x by... the x is what gets aggregated.
So you could write something like
var childrenByAge = from child in class
group getName(child) by child.Age;
This gives you a grouping containing names of children for each age.
Here is a simple example where you can test the difference easily:
static void Main(string[] args)
{
var grouping = from c in "Hello World!"
group c by c; // Replace 'group c by' with 'group 1 by'
// and compare results
foreach (var group in grouping)
{
Console.Write("KEY: {0} VALUES :", group.Key);
foreach (var value in group)
Console.Write(" {0}", value);
Console.WriteLine();
}
Console.ReadKey();
}
I have LINQ statement that has a comma delimited value.
I want to see if my Field matches any of the comma delimited values.
public string IdentifyProductSKU(string Serial)
{
int Len = Serial.Length;
var Split = from ModelSplitter in entities.Models
select ModelSplitter.m_validationMask.Split(',');
var Product = (from ModelI in entities.Models
where ModelI.m_validation == 0 &&
ModelI.m_validationLength == Len &&
ModelI.m_validationMask.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
select ModelI.m_name).SingleOrDefault();
return Product;
}
To explain the code: Every Model has got multiple identifying properties for eg. XX1,XX5,XX7 is all the same product. Now when I pass in a serial number I want to Identify the product based on the validation mask. For eg: XX511122441141 is ProductA and YY123414124 is ProductC. I Just want to split the in this query so in this line:
ModelI.m_validationMask.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
I want to Split the Validation mask To see if the serial contains any of the validation mask characters. Does this make sense?
This is how you split values into a list
var split = context.Packs.Select(u => u.m_validationMask).ToList();
List<String[]> list=new List<String[]>();
foreach (var name in split)
{
String[] str = name.Split(',');
list.Add(str);
}
Now I need to know how I can use that list in my Final EF Query:
int Len = Serial.Length;
var split = entities.Models.Select(u => u.m_validationMask).ToList();
List<String[]> list = new List<String[]>();
foreach (var name in split)
{
String[] str = name.Split(',');
list.Add(str);
}
var Product = (from ModelI in entities.Models
where ModelI.m_validation == 0 &&
ModelI.m_validationLength == Len &&
list.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
select ModelI.m_name).SingleOrDefault();
return Product;
I don't fully understand what you mean or what you are trying to do. But...
If your ModelSplitter.m_malicationMask can indead be split as you had demonstrated, then Split is a List then. What I don't understand is if you are trying to match the entire product A, or just the first three characters, you can modifiy your query
var Product = (from ModelI in entities.Models
where ModelI.m_validation == 0 &&
ModelI.m_validationLength == Len &&
ModelI.m_validationMask.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
let productId = ModelI.m_name.Substring(0, 3)
where split.Contains(productId)
select ModelI.m_name).SingleOrDefault();
Product should now be null if it does not match or an acutal product if it does.
Suppose I have the following list:
var strings = new List<string>();
strings.Add("1");
strings.Add("12.456");
strings.Add("Foobar");
strings.Add("0.56");
strings.Add("zero");
Is there some sort of query I can write in Linq that will return to me only the numeric items, i.e. the 1st, 2nd, and 4th items from the list?
-R.
strings.Where(s => { double ignored; return double.TryParse(s, out ignored); })
This will return all the strings that are parseable as doubles as strings. If you want them as numbers (which makes more sense), you could write an extension method:
public static IEnumerable<double> GetDoubles(this IEnumerable<string> strings)
{
foreach (var s in strings)
{
double result;
if (double.TryParse(s, out result))
yield return result;
}
}
Don't forget that double.TryParse() uses your current culture, so it will give different results on different computers. If you don't want that, use double.TryParse(s, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result).
Try this:
double dummy = 0;
var strings = new List<string>();
strings.Add("1");
strings.Add("12.456");
strings.Add("Foobar");
strings.Add("0.56");
strings.Add("zero");
var numbers = strings.Where(a=>double.TryParse(a, out dummy));
You could use a simple predicate to examine each string, like so:
var strings = new List<string>();
strings.Add("1");
strings.Add("12.456");
strings.Add("Foobar");
strings.Add("0.56");
strings.Add("zero");
var nums = strings.Where( s => s.ToCharArray().All( n => Char.IsNumber( n ) || n == '.' ) );
I want to get a collection of Product entities where the product.Description property contains any of the words in a string array.
It would look something like this (result would be any product which had the word "mustard OR "pickles" OR "relish" in the Description text):
Dim products As List(Of ProductEntity) = New ProductRepository().AllProducts
Dim search As String() = {"mustard", "pickles", "relish"}
Dim result = From p In products _
Where p.Description.Contains(search) _
Select p
Return result.ToList
I already looked at this similar question but couldn't get it to work.
Since you want to see if search contains a word which is contained in the description of p you basically need to test for each value in search if it is contained in the description of p
result = from p in products
where search.Any(val => p.Description.Contains(val))
select p;
This is c# syntax for the lambda method since my vb is not that great
Dim result = From p in products _
Where search.Any(Function(s) p.Description.Contains(s))
Select p
You can use a simple LINQ query, if all you need is to check for substrings:
var q = words.Any(w => myText.Contains(w));
// returns true if myText == "This password1 is weak";
If you want to check for whole words, you can use a regular expression:
Matching against a regular expression that is the disjunction of all the words:
// you may need to call ToArray if you're not on .NET 4
var escapedWords = words.Select(w => #"\b" + Regex.Escape(w) + #"\b");
// the following line builds a regex similar to: (word1)|(word2)|(word3)
var pattern = new Regex("(" + string.Join(")|(", escapedWords) + ")");
var q = pattern.IsMatch(myText);
Splitting the string into words with a regular expression, and testing for membership on the words collection (this will get faster if you use make words into a HashSet instead of a List):
var pattern = new Regex(#"\W");
var q = pattern.Split(myText).Any(w => words.Contains(w));
In order to filter a collection of sentences according to this criterion all you have to do its put it into a function and call Where:
// Given:
// bool HasThoseWords(string sentence) { blah }
var q = sentences.Where(HasThoseWords);
Or put it in a lambda:
var q = sentences.Where(s => Regex.Split(myText, #"\W").Any(w => words.Contains(w)));
Ans From => How to check if any word in my List<string> contains in text by #R. Martinho Fernandes
I decided to group the collection by length of the string.Need suggestion from you to correct myself.
string[] collection = {"five","four","ten","one"};
var groupedValues =
from w in collection
group w by w.Length into getByGroup
select getByGroup;
foreach (var g in groupedValues)
{
Console.WriteLine(g);
}
The output is :
System.Linq.Lookup....
System.Linq.Lookup....
What went wrong ?
GroupBy returns a Lookup object which contains the Key and the collection in the grouping.
foreach (var g in GroupedValues)
{
Console.WriteLine("There are {1} strings of length {0}.", g.Key, g.Count());
foreach (var v in g)
{
Console.WriteLine(" - {0}", v);
}
}
What went wrong depends on what you wanted to do!
The sequence you get back after grouping is not a flat sequence of the original objects (so in your case, it's not a sequence of strings). Otherwise how would they have been grouped?
Maybe given that you apparently expected a flat list of strings, you actually wanted to order them by length:
var collection = new[] {"five","four","ten","one"};
var byLength = collection.OrderBy(s => s.Length);
foreach (var s in GroupedValues)
Console.WriteLine(s);
Or if you wanted to group them, then you have to deal with each group in turn, and each group is a separate list of strings:
foreach (var g in GroupedValues)
{
Console.WriteLine("Strings of length " + g.Key + ":");
foreach (var s in g)
Console.WriteLine(" " + s);
}