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 7 years ago.
Improve this question
how to write dynamic groupby with selectfieldString and resultFieldString?
sample:
public class Customer
{
public int Id;
public string Name;
public string LastName;
public decimal Amount;
}
var lst = new List<Customer>();
lst.Add(new Customer { Id = 1, Name = "vahid", LastName = "Aghilpour", Amount = 15 });
lst.Add(new Customer { Id = 1, Name = "hamid", LastName = "rezaei", Amount = 35 });
lst.Add(new Customer { Id = 1, Name = "vahid", LastName = "Aghilpour", Amount = 15 });
string[] field = { "Name", "LastName" };
string aggrigatefield = "Sum(Amount)";
lst.GroupBy(field).Select(aggrigatefield);---??????????
By using dynamic linq you should be able to do it.
// Remember: using System.Linq.Dynamic;
// The format for the key of the GroupBy is "new(field1,field2)"
// "it" as elementSelector means "the full object"
string field = string.Format("new({0})", string.Join(",", fields));
decimal[] res = lst.GroupBy(field, "it")
.Select(aggrigatefield)
.Cast<decimal>()
.ToArray();
Note that if the Select is totally dynamic (so it could return a Sum(), or a string field, or a decimal field, or a complex object or a ???), then you can't really do a Cast<decimal>(), because you "statically" don't know the type of the returned object. You have to do
object[] res = lst.GroupBy(field, "it")
.Select(aggrigatefield)
.Cast<object>()
.ToArray();
or
dynamic[] res = lst.GroupBy(field, "it")
.Select(aggrigatefield)
.Cast<dynamic>()
.ToArray();
Related
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
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++]);
This question already has answers here:
Split List into Sublists with LINQ
(34 answers)
Closed 3 years ago.
I have a list of n objects (17 for now) and I wanted to know if it is possible to take said list and split it into (potentially) 2 groups. That way the end result would be
NewList
-"GroupA"
-List1 = {"john", "mary", "sam"}
-"GroupB"
-List2 = {"tony", "aaron"}
The desired result would help me output the first half of the list of students in page 1 and then using paging the user can then view the remaining list on the next page.
Right now I am trying to do something like this:
var groupList = Classroom.GroupBy(o => o).Select(grp=>grp.Take((Classroom.Count + 1) / 2)).ToList();
But when I debug it I'm still getting the full list. Can it be done via linq?
You can create group by some property. For example, we have 50 students, then we can make GroupId property and group them by GroupId property:
var students = new List<Student>();
for (int i = 0; i < 50; i++)
{
students.Add(new Student { Id = i, Name = $"Student { i }" });
}
var sectionedStudents = students.Select(s => new
{
GroudId = s.Id / 10,
s.Id,
s.Name
});
var groupedStudents = sectionedStudents.GroupBy(s => s.GroudId);
and Person class:
class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
I want to create a list where it holds several agents and the number of calls they make and did it like so:
public class Agent
{
public string Agent_ID{ get; set; }
public string Name { get; set; }
public int Calls { get; set; }
}
var list = new List<Agent>() // To create a list to hold the data
{
new Agent() { Agent_ID = "TK_J", Name = "James", Calls = 10 },
new Agent() { Agent_ID = "TK_K", Name = "Kurtis", Calls = 10 },
new Agent() { Agent_ID = "TK_R", Name = "Rebecca", Calls = 5 },
new Agent() { Agent_ID = "TK_J", Name = "James", Calls = 10 },
new Agent() { Agent_ID = "TK_R", Name = "Rebecca", Calls = 5 },
new Agents(){ Agent_ID = "TK_B", Name = "Bobby", Calls = 10 },
};
As you can see there will be redundant lines of data. So I want to use C# aggregation function such as group by to sum up the similar agent's number of calls. What I was trying was:
list.GroupBy(i => i.Agent_ID).Select(g => new
{
Agent_ID= g.Key,
Name = */ How do i bring the name here*/,
Calls = g.Sum(i => i.Calls)});
Anyone can help me? Appreciate any help or advice. If there is something wrong teach me how to fix the code. Many thanks!!
You are currently grouping by only AgentID.
You'll need to project the fields you require as an anonymous object so they can be available as an IGrouping<annonymous,Agent> to the select.
See below.
list.GroupBy(i => new {i.Agent_ID, i.Name}).Select(g => new
{
Agent_ID= g.Key.Agent_ID,
Name = g.Key.Name,
Calls = g.Sum(i => i.Calls)
});
Assuming that Agent_ID will be synchronized with the Agent's Name property, you can also use an aggregate like First() to return the the name from any Agent record in the group, since all agents in each group will have the same name:
list.GroupBy(i => i.Agent_ID)
.Select(g => new Agent // Strong class
{
Agent_ID= g.Key.Agent_ID,
Name = g.First().Name,
Calls = g.Sum(i => i.Calls)
})
Also, since you seem to be projecting back into the same shape, why not retain and project into the strong class, rather than a new anon class?
This question already has answers here:
Using Linq to group a list of objects into a new grouped list of list of objects
(5 answers)
Closed 9 years ago.
I have a list that contains string and value of that string but list contains multiple string of same name now i want to group name and add value of that name in single entry. for example
Name ..... Value
apple ----- 2
mango ----- 4
banana ---- 8
apple ----- 4
Now i want to add apple as a single entry.
May be this is what you want:
suppose you have a collection like this:
List<Test> fruits = new List<Test>() { new Test() { Name="Apple", value=3 }
, new Test() {Name="Apple",value=5 }
, new Test() {Name="Orange",value=5 }
};
then you can groupBy it and sum similar items like this:
var netFruits= fruits.GroupBy(s => s.Name)
.Select(s => new Test()
{
Name=s.Key,
value = s.Sum(b=>b.value)
});
where netFruits will have two entries
Apple 8
Orage 5
where Test is:
public class Test
{
public string Name { get; set; }
public int value { get; set; }
}
You can do groupby like this
yourlist.GroupBy(x=>x.YourField())
If I think I know what you want is retreiving distint values. Than this is how it can be do
List<String> MyListOfFruit = new List<String>()
{
{"Banana"},
{"Banana"},
{"Apple"}
};
List<String> GroupedListOfFruits = new List<String>();
GroupedListOfFruits.AddRange(MyListOfFruit.Distinct());
//Now GroupedListOfFruits contains two items: Banana and Apple.
Otherwise post a piece of your code with what kind of list you exactly have. Do you have list of KeyValuePair<String, int> maybe?
So they are separated with "-----"?
var groups = list.Select(str => str.Split(new[]{"-----"}, StringSplitOptions.None))
.Select(split => new { Name = split.First(), Value = split.Last() })
.GroupBy(x => x.Name);
foreach (var grp in groups)
{
Console.WriteLine("Name:{0} Values:{1}", grp.Key, string.Join(",", grp.Select(x => x.Value)));
}
However, it is not clear what you mean with "Now i want to add apple as a single entry".
list.Distinct();
make sure you have included System.Linq in yr namespace.
Since the number of - separating the value from the key seems to be variable, I guess using a Regex to split is more appropriate:
var query = yourlist.Select(x=>{
var arr = Regex.Split(x,#"[-]+");
return new{
Name = arr[0],
Value = Int32.Parse(arr[1])
};
})
.GroupBy(x=>x.Name)
.Select(x=> new{Name = x.Key, Value=x.Sum(y=>y.Value)});
In this way you'll have a new anonymous object, with property Name equal to your string, and property Value equal to the sum of the Values of the elements with such Name.
If, instead you want as a return a string with the sum of the values as value, you can replace the last select with:
.Select(x=> x.Key + " ----- " + x.Sum(y=>y.Value).ToString());
And if, you already have a list with a name and value field, just remove the first Select.