How to speed up grouping and add to dictionary - c#

I have code:
Dictionary<long, List<Data>> daDictTmp = retValTmp
.Where(w => w.IdData.HasValue)
.GroupBy(d => d.IdData.Value)
.ToDictionary(x => x.Key, x => x.ToList());
Is there any other way to do this operation faster?

Related

Dictionary groupings and sum causes An item with the same key has already been added

I have a scenario where in case there is a specific boolean value satisfied (office_debit_total line) I can get amount directly from a column otherwise I need to calculate it by grouping some specific values, here's the code:
var result = products.Select(p => new ResponseDto()
{
customer_id = p.CustomerId,
office_debit_date = p.OfficeDebitDate.Value.ToString(),
office_debit_id = p.OfficeDebitId.ToString(),
office_debit_total = p.OfficeEnum == SomeEnum.ValueType ? p.OfficeAmount.ToString() : totalAmounts[p.OfficeDebitId].ToString(),
payment_method = p.PaymentMethod.Value.ToString(),
}).ToList();
As it's possible to be seen office_debit_total is calculated depending on enum value, and here's dictionary that I'm using to get grouped data:
Dictionary<string, decimal> totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => new { p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod })
.ToDictionary(x => x.Key.OfficeDebitId, x => x.Sum(p => p.Amount));
But I have receiving following error message:
An item with the same key has already been added.
I've tried writing .ToLookup instead of .ToDictionary but that didn't helped me..
Thanks guys
Cheers
If your dictionary has only OfficeDebitId as key then you need to group by only by it:
var totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => p.OfficeDebitId)
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
or use full anonymous object as key:
var totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => new { p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod })
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
Or with value tuple as key:
var totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => (p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod))
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
Why not this:
Dictionary<string, decimal> totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => p.OfficeDebitId)
.ToDictionary(x => x.Key, x => x.Sum(p => p.Amount));
You might need it in this way (You can use value tuple):
Dictionary<(string OfficeDebitId, System.DateTime? OfficeDebitDate, Enumerations.PaymentMethod? PaymentMethod), decimal> totalAmounts = products
.Where(p => p.ProductType == ProductType.ValueType)
.GroupBy(p => new { p.OfficeDebitId, p.OfficeDebitDate, p.PaymentMethod })
.ToDictionary(x => (x.Key.OfficeDebitId, x.Key.OfficeDebitDate, x.Key.PaymentMethod ), x => x.Sum(p => p.Amount));

Converting special object to Dictionary

For y.Value as Excelwert I get null.
My code:
Dictionary<String, List<Excelwert>> kernListe = myList.Where(x => x.Key.Equals(nameDerList))
.ToDictionary(x => x.Key, y => { return new List<Excelwert>(){ y.Value as Excelwert}; });
myList is Dictionary<string,object>.
This is how the Valuelooks like in my watch.
What shall I change ?

How to use GroupBy with ICollections?

I use GroupBy to grouping objects like:
var categories=
tovRDb.MyObjects.AsEnumerable().Where(t => myHashSet.Contains(t.Id))
.GroupBy(t => t.Specialization, t => t,
(key, g) => new {Name = key.Name, CategoryItems = g.ToList()})
.OrderBy(t => string.IsNullOrEmpty(t.Name))
.ThenBy(t => t.Name)
.ToList();
It's works fine.
But now i want to group objects where Specialization is ICollection<>.
For example:
MyObject1: "Berlay's Meat"
Specializations{Chicken, Pork, Beef}
MyObject2: "Wonday's Chickery"
Specializations{Chicken}
MyObject3: "Rooki's Meat"
Specializations{Chicken, Pork}
And after group by:
Pork{MyObject1: "Berlay's Meat",MyObject3: "Rooki's Meat"}
Beef{MyObject1: "Berlay's Meat"}
Chicken{MyObject1: "Berlay's Meat",MyObject2: "Wonday's Chickery", MyObject3: "Rooki's Meat"}
Any advises?
Withcategories as:
var categories = tovRDb.MyObjects.AsEnumerable().Where(t => myHashSet.Contains(t.Id));
var catsGrouped = categories.SelectMany(
x => x.Specializations, // Specializations is an IEnumerable<Specialization>
(x, y) => new
{
Category = x,
Specialization = y,
}).GroupBy(x => x.Specialization, x => x.Category)
.ToArray();
I used the SelectMany to "multiply" each category for its specializations... Then I regrouped the result by Specialization. The result is a IGrouping<Specialization, MyObject>[]

Get one child element per group

I am getting, with EF6, one advert by position as follows:
var adverts = context.Adverts
.Include(x => x.Files)
.Where(x => x.Position <= 32)
.OrderBy(x => Guid.NewGuid())
.GroupBy(x => x.Position)
.ToDictionary(x => x.Key, x => x.First());
I get one advert per group and each advert has one file.
But what I really want is a file for each advert so I tried:
var adverts = context.Adverts
.Include(x => x.Files)
.Where(x => x.Position <= 32)
.OrderBy(x => Guid.NewGuid())
.GroupBy(x => x.Position)
.ToDictionary(x => x.Key, x => x.First().Files);
In this case the value of the dictionary is empty.
Any idea how to solve this?

Linq Expression to Turn DataTable to Dictionary of <Key, List<Values>>

I am trying to convert a DataTable of the form
Key Value
1 A
1 B
1 C
2 X
2 Y
To a Dictionary
1 [A,B,C]
2 [X,Y]
The lambda expression I am using is
GetTable("..sql..").AsEnumerable().
.Select(r => new {Key = r.Field<int>("Key"), Val = r.Field<string>("Value")})
.GroupBy(g => g.Key)
.ToDictionary(a => a.Key, a => String.Join(",", a.Value))
But it fails with "Cannot convert lambda expression to type 'System.Collections.Generic.IEqualityComparer' because it is not a delegate type"
How can I accomplish this?
This does it:
GetTable("..sql..").AsEnumerable().
.Select(r => new {Key = r.Field<int>("Key"), Val = r.Field<string>("Value")})
.GroupBy(g => g.Key)
.ToDictionary(a => a.Key, a => String.Join(",", a.Select(x => x.Value).ToList()))
Here's another way you can do it...
GetTable("..sql..").AsEnumerable()
.GroupBy(x => x.Field<int>("Key"))
.ToDictionary(grp => grp.Key, x => x.Select(y => y.Field<string>("Value")).ToList());
var foo = GetTable("").AsEnumerable()
.ToLookup(x => x.Key, x => x.Value);
foreach(var x in foo)
{
foreach(var value in x)
{
Console.WriteLine(string.Format("{0} {1}", x.Key, value));
}
}

Categories

Resources