GroupBy String and Count in LINQ - linq

I have got a collection. The coll has strings:
Location="Theater=1, Name=regal, Area=Area1"
Location="Theater=34, Name=Karm, Area=Area4445"
and so on. I have to extract just the Name bit from the string. For example, here I have to extract the text 'regal' and group the query. Then display the result as
Name=regal Count 33
Name=Karm Count 22
I am struggling with the query:
Collection.Location.GroupBy(????);(what to add here)
Which is the most short and precise way to do it?

Yet another Linq + Regex approach:
string[] Location = {
"Theater=2, Name=regal, Area=Area1",
"Theater=2, Name=regal, Area=Area1",
"Theater=34, Name=Karm, Area=Area4445"
};
var test = Location.Select(
x => Regex.Match(x, "^.*Name=(.*),.*$")
.Groups[1].Value)
.GroupBy(x => x)
.Select(x=> new {Name = x.Key, Count = x.Count()});
Query result for tested strings

Once you've extracted the string, just group by it and count the results:
var query = from location in locations
let name = ExtractNameFromLocation(location)
group 1 by name in grouped
select new { Name=grouped.Key, Count=grouped.Count() };
That's not particularly efficient, however. It has to do all the grouping before it does any counting. Have a look at this VJ article for an extension method for LINQ to Objects,
and this one about Push LINQ which a somewhat different way of looking at LINQ.
EDIT: ExtractNameFromLocation would be the code taken from answers to your other question, e.g.
public static string ExtractNameFromLocation(string location)
{
var name = (from part in location.Split(',')
let pair = part.Split('=')
where pair[0].Trim() == "Name"
select pair[1].Trim()).FirstOrDefault();
return name;
}

Here is another LINQ alternative solution with a working example.
static void Main(string[] args)
{
System.Collections.Generic.List<string> l = new List<string>();
l.Add("Theater=1, Name=regal, Area=Area"); l.Add("Theater=34, Name=Karm, Area=Area4445");
foreach (IGrouping<string, string> g in l.GroupBy(r => extractName(r)))
{
Console.WriteLine( string.Format("Name= {0} Count {1}", g.Key, g.Count()) );
}
}
private static string extractName(string dirty)
{
System.Text.RegularExpressions.Match m =
System.Text.RegularExpressions.Regex.Match(
dirty, #"(?<=Name=)[a-zA-Z0-9_ ]+(?=,)");
return m.Success ? m.Value : "";
}

Related

LINQ with list<int> quering the Value of a Dictonary<int, object>

I have a problem with a query. I have a List with int and want to use it to get the values from my dictionary. The dictionary-keys are int and some of them have the value of the list-items. My question is how i get the objects out of the dictionary, thats keys matces the list items. Was programming JAVA the last years and now struggling with LINQ :(
Thanks in advance
Problem solved. Thank you all :)
No idea how to close this topic. I am reading stackoverflow since one year, but this was my first post.
You can use Linq to join list items with dictionary KeyValuePair entries on entry key. And then select entry value from each joined pair:
var values = from l in list
join kvp in dictionary on l equals kvp.Key
select kvp.Value;
Lambda syntax:
var values = list.Join(dictionary, l => l, kvp => kvp.Key, (l,kvp) => kvp.Value);
Basically:
var value = dictionary[integerKey];
Or:
if (dictionary.TryGetValue(integerKey, out value)) {
}
You can also create an extension method:
public static class DictionaryExtensions
{
public static IEnumerable<TValue> FilterValuesBy<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, IEnumerable<TKey> filter)
{
if (dictionary == null) throw new ArgumentNullException("dictionary");
if (filter == null) throw new ArgumentNullException("filter");
var coll = filter as ICollection<TKey> ?? new HashSet<TKey>(filter);
return dictionary.Where(kvp => coll.Contains(kvp.Key)).Select(kvp => kvp.Value);
}
}
Usage:
class Program
{
static void Main()
{
var dict = Enumerable.Range(0, 10).ToDictionary(x => x);
var filter = Enumerable.Range(0, 2);
foreach (var i in dict.FilterValuesBy(filter))
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
Simple Linq method chain:
var dict = Enumerable.Range(0, 10).ToDictionary(x => x);
var filter = Enumerable.Range(0, 2).ToList();
var filtered = dict.Where(x => filter.Contains(x.Key)).Select(x => x.Value).ToList();

Find / Count Redundant Records in a List<T>

I am looking for a way to identify duplicate records...only I want / expect to see them.
So the records aren't duplicated completely but the unique fields I am unconcerned with at this point. I just want to see if they have made X# payments of the exact same amount, via the exact same card, to the exact same person. (Bogus example just to illustrate)
The collection is a List<> further whatever X# is the List<>.Count will be X#. In other words all the records in the list match (again just the fields I am concerned with) or I will reject it.
The best I can come up with is to take the first record get value of say PayAmount and LINQ the other two to see if they have the same PayAmount value. Repeat for all fields to be matched. This seems horribly inefficient but I am not smart enough to think of a better way.
So any thoughts, ideas, pointers would be greatly appreciated.
JB
Something like this should do it.
var duplicates = list.GroupBy(x => new { x.Amount, x.CardNumber, x.PersonName })
.Where(x => x.Count() > 1);
Working example:
class Program
{
static void Main(string[] args)
{
List<Entry> table = new List<Entry>();
var dup1 = new Entry
{
Name = "David",
CardNumber = 123456789,
PaymentAmount = 70.00M
};
var dup2 = new Entry
{
Name = "Daniel",
CardNumber = 987654321,
PaymentAmount = 45.00M
};
//3 duplicates
table.Add(dup1);
table.Add(dup1);
table.Add(dup1);
//2 duplicates
table.Add(dup2);
table.Add(dup2);
//Find duplicates query
var query = from p in table
group p by new { p.Name, p.CardNumber, p.PaymentAmount } into g
where g.Count() > 1
select new
{
name = g.Key.Name,
cardNumber = g.Key.CardNumber,
amount = g.Key.PaymentAmount,
count = g.Count()
};
foreach (var item in query)
{
Console.WriteLine("{0}, {1}, {2}, {3}", item.name, item.cardNumber, item.amount, item.count);
}
Console.ReadKey();
}
}
public class Entry
{
public string Name { get; set; }
public int CardNumber { get; set; }
public decimal PaymentAmount { get; set; }
}
The meat of which is this:
var query = from p in table
group p by new { p.Name, p.CardNumber, p.PaymentAmount } into g
where g.Count() > 1
select new
{
name = g.Key.Name,
cardNumber = g.Key.CardNumber,
amount = g.Key.PaymentAmount,
count = g.Count()
};
You're unique entries are based off of the 3 criteria of Name, Card Number, and Payment Amount so you group by them and then use .Count() to count how many of those unique values exist. where g.Count() > 1 filters the group to duplicates only.

Linq query Group By multiple columns

I have a array of string say:
String[] Fields=new String[]{RowField,RowField1}
In which I can use the below query to get the values by specifying the values is query i.e RowField and RowField1:
var Result = (
from x in _dataTable.AsEnumerable()
select new
{
Name = x.Field<object>(RowField),
Name1 = x.Field<object>(RowField1)
})
.Distinct();
But if suppose I have many values in the Array like:
String[] Fields= new String[]
{
RowField,
RowField1,
RowField2,
.......
RowField1000
};
How can I use the query here without specifying each of the rowfield in the query?
How can i iterate through the array items inside the LINQ?
According to some suggestions in LINQ query and Array of string I am trying to get the result using the code below.
var result = (from row in _dataTable.AsEnumerable()
let projection = from fieldName in fields
select new {Name = fieldName, Value = row[fieldName]}
select projection.ToDictionary(p=>p.Name,p=>p.Value))
.Distinct();
But the problem is it does not return the distinct values.Any ideas?
Start with distinct DataRows by using this overload of Distinct():
_dataTable.AsEnumerable().Distinct(new DataRowEqualityComparer())
Where DataRowEqualityComparer is:
public class DataRowEqualityComparer : IEqualityComparer<DataRow>
{
public bool Equals(DataRow x, DataRow y)
{
return x.ItemArray.SequenceEqual(y.ItemArray);
}
public int GetHashCode(DataRow obj)
{
return string.Join("", obj.ItemArray).GetHashCode();
}
}

linq select from database where ID in an ArrayList

I have an array-list that contains some UserID.
I need a query like this:
vat tmp= users.select(a=> a.UserID in (arraylist));
what can I do?
If it's actually in an ArrayList, you should create a List<T> or array first. Then you can use Contains:
// Use the appropriate type, of course.
var ids = arraylist.Cast<string>().ToList();
var tmp = users.Select(a => ids.Contains(a.UserID));
While using Contains on the plain ArrayList may well compile, I would expect it to fail at execution time, assuming users is an IQueryable<>.
List<long> list =new List<long>();
var selected = from n in users where list.Contains(n.ID) select n ;
OR
var selected = users.Where(a=> list.Contains(a.ID)).ToList();
This is the solution I used.
public static IEnumerable<SettingModel> GetSettingBySettingKeys(params string[] settingKey)
{
using (var db = new BoxCoreModelEntities())
{
foreach (var key in settingKey)
{
var key1 = key;
yield return Map(db.Settings.Where(s => s.SettingKey == key1).First());
}
}
}

Need help with formulating LINQ query

I'm building a word anagram program that uses a database which contains one simple table:
Words
---------------------
varchar(15) alphagram
varchar(15) anagram
(other fields omitted for brevity)
An alphagram is the letters of a word arranged in alphabetical order. For example, the alphagram for OVERFLOW would be EFLOORVW. Every Alphagram in my database has one or more Anagrams. Here's a sample data dump of my table:
Alphagram Anagram
EINORST NORITES
EINORST OESTRIN
EINORST ORIENTS
EINORST STONIER
ADEINRT ANTIRED
ADEINRT DETRAIN
ADEINRT TRAINED
I'm trying to build a LINQ query that would return a list of Alphagrams along with their associated Anagrams. Is this possible?
UPDATE: Here's my solution based on the suggestions below! Thanks all!
using (LexiconEntities ctx = new LexiconEntities())
{
var words = ctx.words;
var query =
from word in words
where word.alphagram == "AEINRST"
group word by word.alphagram into alphagramGroup
select new { Alphagram = alphagramGroup.Key, Anagrams = alphagramGroup };
foreach (var alphagramGroup in query)
{
Console.WriteLine("Alphagram: {0}", alphagramGroup.Alphagram);
foreach (var anagram in alphagramGroup.Anagrams)
{
Console.WriteLine("Anagram: {0}", anagram.word1);
}
}
}
var list = anagrams.Select(
a => new {
Alphagram = a.ToCharArray().OrderBy(s => s).ToString(),
Anagram = a
}).toList();
A totally new answer...
You seem to need a groupby query look at How to: Group Data (Entity Framework).
this should accomplish what you want...
I did a testy with LINQ and this works...
var words = new List<Word>()
{
new ConsoleApplication1.Word("EINORST", "NORITES"),
new ConsoleApplication1.Word("EINORST", "OESTRIN"),
new ConsoleApplication1.Word("EINORST", "STONIER"),
new ConsoleApplication1.Word("ADEINRT", "ANTIRED"),
new ConsoleApplication1.Word("ADEINRT", "DETRAIN"),
new ConsoleApplication1.Word("ADEINRT", "TRAINED")
};
var q = words.GroupBy(w => w.Alphagram).Select(w => new { Alphagram = w.Key, Anagrams = w.Select(p => p.Anagram).ToList() }).ToList();
foreach (var item in q)
{
Console.WriteLine("Alphagram : {0}, Anagrams = {1}", item.Alphagram, String.Join(",", item.Anagrams));
}
var words = new List<Words>()
{
new Words("EINORST", "NORITES"),
new Words("EINORST", "OESTRIN"),
new Words("EINORST", "STONIER"),
new Words("ADEINRT", "ANTIRED"),
new Words("ADEINRT", "DETRAIN"),
new Words("ADEINRT", "TRAINED")
};
var result = words.GroupBy(w => w.Alphagram, w => w.Anagram)
.Select(w => new {
Alphagram = w.Key,
Anagrams = w.Where(p => w.Key.ToCharArray().SequenceEqualUnOrdered(p.ToCharArray())).ToList()
}
)
.ToList();
public static bool SequenceEqualUnOrdered<T>(this IEnumerable<T> first, IEnumerable<T> second)
{
return new HashSet<T>(first).SetEquals(second);
}
Is it what you are looking for? It is LINQ to Objects. You may want to use LINQ-to-SQL or LINQ-to-Entites to fetch your records into your objects and then use the above-mentioned LINQ-to-Objects query over the already-fetched object collection.

Resources