LINQ GroupBy or something else for a single loop? [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
This object (greatly simplified) is basically this:
public class Site
{
public string SiteId { get; set; }//unique
public string SiteName { get; set; }
public string NetworkId { get; set; } //unique
public string NetworkName { get; set; }
}
I would like the end result to be:
Network 1
Site 1
Site 2
Network 2
Site 1
Site 2
Site 3
Edit for clarity:
I could just outer loop all the networks and then inner loop all the sites that belong to that network.
I'm using 2 loops. One outer one for the unique NetworkId and one inner one for the unique SiteId.
I was wondering if there was a way to accomplish the same result with a single loop. I realize that a GroupBy return IEnumerable<IGrouping<TKey, TElement>> but I'm not sure how to use that for my preferred result.
Edit adding details:
Can I accomplish the end result in a single foreach loop if I use a GroupBy?
How would I accomplish the end result output if I used a GroupBy on the NetworkId?
thanks!

Yes, GroupBy is your friend. What should be the end result? Maybe a Dictionary<(string, string), List<Site>> where the key is the combination of NetworkId and NetworkName(in case the name is not unique)?
Dictionary<(string Id, string Name), List<Site>> networkSites = allSites
.GroupBy(s => (s.NetworkId, s.NetworkName))
.ToDictionary(g => g.Key, g => g.OrderBy(s => s.SiteId).ToList());
Output:
foreach(var kv in networkSites)
{
Console.WriteLine($"{kv.Key.Name} {kv.Key.Id}");
foreach(var site in kv.Value)
Console.WriteLine($"{site.SiteName} {site.SiteId}");
}

using linq
var result = sites.GroupBy(x => x.NetworkName).ToDictionary(x => x.Key, y => y.Select(x=>x.SiteId).ToArray());

Rather than GroupBy followed by ToDictionary, you could create a lookup:
var lookup = sites.ToLookup(x => x.NetworkId, x => x.SiteId);
The Lookup<TKey, TValue> is an immutable structure that allows an IEnumerable<TValue> to be retrieved using an indexer:
var sitesForNetwork1 = lookup[1];

Related

C# Join string from object with LINQ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last month.
Improve this question
I currently have an object that I have defined like this.
public class Model {
public string id {get; set;}
public string customer {get; set;}
public string sentence {get; set;}
}
When working with my object I do it in collections which can have repeated elements by id and customer but different sentence, I need to iterate the common elements and join it's sentence like so:
id
customer
sentence
1
001
why
1
001
that
2
002
seperate
I am trying to convert this to the following:
id
customer
sentence
1
001
why, that
2
002
seperate
I currently have this code:
List<Model> data = JsonConvert.DeserializeObject<List<Model>>(json);
List<Model> result = data.GroupBy(x => new {
x.id,
x.customer
}).Select(x => new Model {
id = x.Key.id,
customer = x.Key.customer,
sentence = String.Join(", ", x.Select(z => z.sentence)) // this is what I need to fix
}).ToList();
This however doesn't seem to work, what can I do to fix this. Can anyone help me with this? Thanks in advance.
EDIT:
The tables shown are the visual representation of a List, the first one would be the data variable and the last one how I want the result variable to be. The code doesn't work, it will still return the first visual representation.
My apologies for the unclear question.
There's a code typo, the following works as you need:
List<Model> data = JsonConvert.DeserializeObject<List<Model>>(json);
List<Model> result = data.GroupBy(x => new {
x.id,
x.customer
}).Select(x => new Model {
id = x.Key.id,
customer = x.Key.customer,
sentence = string.Join(", ", x.Select(z => z.sentence))
}).ToList();
Output:
1|001|why, that
2|002|seperate

C# LINQ Combine values of 2 lists [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a list with tickets in it:
TicketID - Aantal (amount) - ActiePrijs (price)
For all those tickets the ActiePrijs (price) is still empty. But I also have a list with only those Actieprijs (prices). It's just a list of decimals.
Now I want to put the first actiePrijs from the decimal list into the ActiePrijs from the first ticket, the second ActiePrijs into the ActiePrijs of the second ticket etc.
I want to do it using linq method syntax.
Can someone help me?
I assume tickets & price lists are tickets and price.
You can use linq like below.
tickets = tickets.Select((ticket, index) => new Ticket
{
TicketID = ticket.TicketID,
Aantal = ticket.Aantal,
ActiePrijs = price[index]
})
.ToList();
Or if you have more properties and you do not want to create new object then use like below.
tickets = tickets.Select((ticket, index) =>
{
ticket.ActiePrijs = price[index];
return ticket;
})
.ToList();
You dont show any code, but I thing you want something like this.
public class Properties
{
public int Aantal { get; set; }
public int Price { get; set; }
}
List<Properties> l = new List<Properties>();
l.Add(new Properties() { Aantal = 1 });
l.Add(new Properties() { Aantal = 2 });
l.Add(new Properties() { Aantal = 3 });
List<int> l2 = new List<int>();
l2.Add(1);
l2.Add(2);
l2.Add(3);
int index = 0;
l.ForEach(x => x.Price = l2[index++]);

Dictionary problems: results.Read<NotificationRule>().ToDictionary(rule => rule.Id) states duplicate key

I have a slight problem I don't seem to understand.
I have this bit of code:
SELECT sr.RuleId, s.Id, s.Name FROM Sites s
INNER JOIN NotificationSiteRules sr ON s.Id = sr.SiteID
WHERE sr.RuleId IN (
SELECT r.Id FROM NotificationRules r
INNER JOIN NotificationSiteRules sr ON r.Id = sr.RuleId
WHERE r.IsDeleted = 0 AND (#siteId IS NULL OR sr.SiteId = #siteId)
)
which returns the following set:
1 1 SiteOne
3 1 SiteOne
7 1 SiteOne
1 5 SiteTwo
As you can see, for rule 1 I have both SiteOne and SiteTwo. This must be permitted.
The definition of NotificationRule object is:
public class NotificationRule
{
public NotificationRule()
{
Sites = new List<Site>();
Recipients = new List<Recipient>();
}
public int? Id { get; set; }
public string Name { get; set; }
public List<Site> Sites { get; set; }
public List<Recipient> Recipients { get; set; }
}
So in this definition, it's actually stated that by each Id I should be able to have a list of Sites... But I am getting
System.ArgumentException: An item with the same key has already been added.
when I do
var rules = results.Read<NotificationRule>().ToDictionary(rule => rule.Id);
What am I doing wrong?
Sorry, I am editing the question because I am afraid I was not clear as to what I am trying to achieve.
The final result I was hoping for is of this form:
{1, [1,5],[SiteOne, SiteTwo]}
Which would correspond to:
{Key, List<Recipient>, list<Site>}
As you can see, in this construct I wouldn't have two keys, because all ends up into the same element.
As long as objects in the collection results have not unique values in the field Id you have to group results before put them to the dictionary.
results.Read<NotificationRule>()
.GroupBy(rule=>rule.Id).ToDictionary(group => group.Key, group=>group.ToArray());
It sounds like you may be wanting to do a group by rather than creating a dictionary.
var rules = results.Read<NotificationRule>().GroupBy(k => rule.Id);
This will group the rules by rule.Id
or if you are just trying to get the sites for a specific rule you could do
var siteId = 1;
var sites = results.Read<NotificationRule>().Where(r => r.Id == siteId);
Actually I just found that the problem is not in that little bit of code; that one is handled ok. The problem is that #siteId is arriving null, and then I get duplicates in a previous query.
I am closing this question as the point is now moot; I need to figure out a way to fix the previous query to get me the correct value... or a way to handle that null.
Thank you all for your help!

convert generic type result to class in lambda expression entity framework in c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am trying to retrieve role info as below:
var allRoles = (from roles in context.aspnet_Roles
select new { roles.RoleId, roles.RoleName }).ToList();
I want to store these role data to a specific class type or LIST<string> not to object of type var like allRoles.
You are currently selecting a list of anonymous type. What you seem to want is just the name and as such you should select just the name as a result instead of projecting a new object.
var allRoles = (from roles in context.aspnet_Roles
select roles.RoleName).ToList();
To change the things stored in the list, you change the bit after the select keyword. For example:
var allRoles = (from roles in context.aspnet_Roles
select "ID=" + roles.RoleId + ";Name=" + roles.RoleName).ToList();
The specific expression following the keyword will depend on the string format you want for the list's elements.
By the way, this code does not have any lambda expressions in it.
What I understand from these details is that there are a few columns in "context.aspnet_Roles" but, you only want to use RoleId and RoleName.
Here is what I would do :
List<MagicClass> allRoles= new List<MagicClass>();
allRoles= (from roles in context.aspnet_Roles
select new MagicClass
{
RoleId = roles.RoleId,
RoleName = roles.RoleName
}).ToList();
internal class MagicClass
{
private string RoleId {get;set;}
private string RoleName {get;set;}
};
Hope this helps.
I would suggest if you want to store role name only use this
var allRoles = (from roles in context.aspnet_Roles
select new { roles.RoleName }).ToList();

Group by custom list linq c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have problem in understanding custom group by and order by. Here is the scenario,
I have an object contain data.
Objects->object->name; (structure of the object)
and i want to group by custom list that i have (name is the key object for grouping).
name is like a,b,c and i want b,c,a(sample).
Here is my work around
IOrderedEnumerable<IGrouping<string, Snit>> assetGrouping = sUnits.ToArray().GroupBy(e => e.Name).OrderBy(e => e.Key);
and i want to group and order by my custom list
List<string > customOrder=new List<string>();
customOrder.Add("any");
customOrder.Add("some");
can any body help me..
This is what I scrapped using LINQPad:
Prerequisites:
public class Data
{
public string Name {get; set;}
}
var keys = new[]{"1", "15", "13", "16"};
var random = new Random();
var data = Enumerable.Range(1, 100)
.Select( _ => new Data
{
Name = random.Next(24).ToString()
});
var keys = new[]{"1", "15", "13", "16"};
Now, the grouping:
var grouped = data.GroupBy(x => keys.FirstOrDefault(k=>k==x.Name));
The query above will group the items in data as following: for each value x in data, if there is a key k in keys with k == x.Name, the value will be added to a separate group having the key k; all the other values will be added to a separate group having the key null;
For the ordering of the groups you just need to use the position of each group key in the keys array.
var ordered = grouped.OrderBy( g =>
{
var index = Array.IndexOf(keys, g.Key);
return index == -1 ? int.MaxValue : index;
});
Array.IndexOf will return -1 if the item wasn't found in the dictionary. In this case, according to your needs, the item must be at the end of the collection so return max value. Otherwise, just use the index of the key.
The results are in the image below:

Categories

Resources