How to sort the given examples.
IEnumerable<extra> eList = new List<extra>()
{
new extra{ id = 1, text = "a"},
new extra{ id = 2, text = "g"},
new extra{ id = 3, text = "i"},
new extra{ id = 4, text = "e"},
new extra{ id = 5, text = "f"},
new extra{ id = 6, text = "d"},
new extra{ id = 7, text = "c"},
new extra{ id = 8, text = "h"},
new extra{ id = 9, text = "b"}
};
IEnumerable<sample> sam = new List<sample>()
{
new sample{ id = 1, name = "sample 1", list = new List<int>{1,5,6}},
new sample{ id = 2, name = "sample 1", list = new List<int>{2,9}},
new sample{ id = 3, name = "sample 1", list = new List<int>{8,3,7}},
new sample{ id = 4, name = "sample 1", list = new List<int>{3,4,8}},
new sample{ id = 5, name = "sample 1", list = new List<int>{1,5,7}},
new sample{ id = 6, name = "sample 1", list = new List<int>{6,9,7}}
};
I have this code to sort and join the sample list to the extra object above.
var s2 = (from d1 in sam
select new
{
name = d1.name,
id = d1.id,
list =
(
from d2 in d1.list
join e in eList on d2 equals e.id
select new {
id = d2, text = e.text
}
).OrderBy(item => item.text.FirstOrDefault())
});
The code above works fine, it joined the two data and sorted the values for the list. But what I want is the output above 's2' will be sorted again by its 'list' value by 'list.text'.
So possible output above must be:
{ id = 1, name = "sample 1", list = {'a','f','d'}},
{ id = 5, name = "sample 1", list = {'a','f','c'}},
{ id = 2, name = "sample 1", list = {'g','b'}},
{ id = 4, name = "sample 1", list = {'i','e','h'}},
{ id = 6, name = "sample 1", list = {'d','b','c'}},
{ id = 3, name = "sample 1", list = {'h','i','c'}},
Is this possible in LINQ?
thanks
var newsam = sam.Select(s => new
{
id = s.id,
name = s.name,
list = s.list
.Select(l => eList.FirstOrDefault(e => e.id == l).text)
.OrderBy(e => e)
.ToList()
}
).OrderBy(s => s.list.FirstOrDefault())
.ToList();
EDIT
So, the inner lists are sorted by the text value of the eList; and the outer list is sorted by the first element of the inner list
EDIT
var s2=(from d1 in sam
select new
{
name = d1.name,
id = d1.id,
list =
(
from d2 in d1.list
join e in eList on d2 equals e.id
select e.text
).OrderBy(item => item).ToList()
}).OrderBy(item => item.list.FirstOrDefault());
Related
I want to make one collection of three according to certain conditions (with LINQ). let's say I have a Class:
class Collection
{
public int id;
public string name;
public double weight;
}
Then I'm creating collections:
List<Collection> collection1 = new()
{
new Collection() { id = 11, name = "Abraham 1", weight = 1.1 },
new Collection() { id = 12, name = "Abraham 2", weight = 1.2 },
new Collection() { id = 13, name = "Abraham 3", weight = 1.3 },
};
List<Collection> collection2 = new()
{
new Collection() { id = 21, name = "Bill 1", weight = 2.1 },
new Collection() { id = 22, name = "Bill 2", weight = 2.2 },
new Collection() { id = 23, name = "Bill 3", weight = 2.3 },
};
List<Collection> collection3 = new()
{
new Collection() { id = 31, name = "David 1", weight = 3.1 },
new Collection() { id = 32, name = "David 2", weight = 3.2 },
new Collection() { id = 33, name = "David 3", weight = 3.3 },
};
TODO 1. Condition: get 1st column from 1st collection, 2nd column from 2nd collection, 3rd column from 3rd column. result should be:
{
new Collection() { id = 11, name = "Bill 1", weight = 3.1 },
new Collection() { id = 12, name = "Bill 2", weight = 3.2 },
new Collection() { id = 13, name = "Bill 3", weight = 3.1 }
}
TODO 2. Second case condition: get first elements from columns of all collections. result should be:
{
new Collection() { id = 11, name = "Abraham 1", weight = 1.1 },
new Collection() { id = 21, name = "Bill 1", weight = 2.1 },
new Collection() { id = 31, name = "David 1", weight = 3.1 }
}
Please help.
Using C# 10 and .Net 6, just use Enumerable.Zip:
var todo1 = collection1.Zip(collection2, collection3)
.Select(t => new Collection { id = t.First.id, name = t.Second.name, weight = t.Third.weight })
.ToList();
var todo2 = collection1.Zip(collection2, collection3)
.Select(t => new List<Collection> { t.First, t.Second, t.Third })
.First();
If you don't have the three argument Zip that returns a tuple, just roll your own, e.g. for Todo1:
var td1 = collection1.Zip(collection2, (c1, c2) => (c1, c2))
.Zip(collection3, (t12, c3) => (First: t12.c1, Second: t12.c2, Third: c3))
.Select(t => new Collection { id = t.First.id, name = t.Second.name, weight = t.Third.weight })
.ToList();
If you want to merge multiple collections into one collection using LINQ then do this:
List<Collection> result = collection1.Concat(collection2).OrderBy(x => x.id).ToList();
I would like to select only from non-blank Names where any Group contains same ID multiple times:
Data Setup
var a1 = new { id = 3, Name = "", Group = "GroupA" };
var a2 = new { id = 2, Name = "", Group = "GroupA" };
var a3 = new { id = 3, Name = "", Group = "GroupA" };
var b1 = new { id = 4, Name = "B", Group = "GroupB" };
var b2 = new { id = 5, Name = "B", Group = "GroupB" };
var b3 = new { id = 5, Name = "B", Group = "GroupB" };
List<dynamic> group = new List<dynamic>();
group.Add(a1);
group.Add(a2);
group.Add(a3);
group.Add(b1);
group.Add(b2);
group.Add(b3);
Query:
var query1 = group.ToList()
.Where(s=>s.Name != "")
.GroupBy(x =>x.Group)
.Where(g => g.Count() > 1)
.SelectMany(y => y)
.ToList();
Console.WriteLine("output\n" + string.Join("\n", query1));
Returns
id = 4, Name = B, Group = GroupB
id = 5, Name = B, Group = GroupB
id = 5, Name = B, Group = GroupB
But what I wanted is the following:
id = 5, Name = B, Group = GroupB
id = 5, Name = B, Group = GroupB
What am I doing wrong?
Group by id and/or Name depending on your needs
.GroupBy(x => new {x.id, x.Name})
Given
var list = new[]
{
new {id = 3, Name = "", Group = "GroupA"},
new {id = 2, Name = "", Group = "GroupA"},
new {id = 3, Name = "", Group = "GroupA"},
new {id = 4, Name = "B", Group = "GroupB"},
new {id = 5, Name = "B", Group = "GroupB"},
new {id = 5, Name = "B", Group = "GroupB"}
};
Usage
var results = list
.Where(s => s.Name != "")
.GroupBy(x => new {x.id, x.Name})
// .GroupBy(x => x.id) <- depending on your needs
.Where(g => g.Count() > 1)
.SelectMany(y => y);
foreach (var result in results)
Console.WriteLine($"{result.id}, {result.Name}, {result.Group}");
Output
5, B, GroupB
5, B, GroupB
You are applying GroupBy to Group property. Instead of Grouping by Group property, use id property,
Input
var list = new[]
{
new {id = 3, Name = "", Group = "GroupA"},
new {id = 2, Name = "", Group = "GroupA"},
new {id = 3, Name = "", Group = "GroupA"},
new {id = 4, Name = "B", Group = "GroupB"},
new {id = 5, Name = "B", Group = "GroupB"},
new {id = 5, Name = "B", Group = "GroupB"}
};
Solution:
var query1 = list.ToList()
.Where(s=>s.Name != "")
.GroupBy(x =>x.id)
//^^^^^ This change you need to do
.Where(g => g.Count() > 1)
.SelectMany(y => y)
.ToList();
Output
5, B, GroupB
5, B, GroupB
Try it online
I have a list of object (ProductInfo).
ProductInfo contains an id, name, and an option.
Imagine this sample, i have this
ProductInfo Id => 1, Name => XXX, Option = A
ProductInfo Id => 1, Name => XXX, Option = B
ProductInfo Id => 2, Name => DEB, Option = A
ProductInfo Id => 2, Name => DEB, Option = B
ProductInfo Id => 2, Name => DEB, Option = C
ProductInfo Id => 3, Name => ZZZ, Option = D
....
....
We see we have 2 time the option A AND B for product 1 and 2.
My goal will be to obtain the max repeat item for each product in the list.
i would like to obtain as result this :
Id = 1, Name = XXX = A, count = 2
Id =2, Name = DEB, count = 2
How i can do that ?
thanks for your time
try to do this code:
var list = new List<ProductInfo> {
new ProductInfo { Id = 1, Name = "XXX", Option = "A"},
new ProductInfo { Id = 1, Name = "XXX", Option = "B" },
new ProductInfo { Id = 2, Name = "DEB", Option = "A" },
new ProductInfo { Id = 2, Name = "DEB", Option = "B"},
new ProductInfo { Id = 2, Name = "DEB", Option = "C" },
new ProductInfo { Id = 3, Name = "ZZZ", Option = "D" }
};
var x = from p in list
group p by new { p.Id, p.Name, p.Option } into g
select new
{
Id = g.Key.Id,
Name = g.Key.Name,
Count = list.Count(m => m.Name == g.Key.Name)
};
var t = x.Distinct();
You can use GroupBy on the Name and Id parameter. Sorry read that wrong at first.
I have 2 listitems
First
{Id = 1, Name = "a"}{Id = 2, Name = "b"}{Id = 3, Name = "c"}
Second
{Id = 2, Name = "b"}{Id = 3, Name = "c"}{Id = 4, Name = "d"}
how to merge them and get a listitem like:
{Id = 1, Name = "a"}{Id = 2, Name = "b"}{Id = 3, Name = "c"}{Id = 4, Name = "d"}
Something like this ?
class items {
public int id;
public string name;
}
static void Main(string[] args)
{
var list = new List<items>();
list.Add(new items {id=1 , name="a"});
list.Add(new items { id = 2, name = "b" });
list.Add(new items { id = 3, name = "c" });
var list1 = new List<items>();
list1.Add(new items { id = 2, name = "b" });
list1.Add(new items { id = 3, name = "c" });
list1.Add(new items { id = 4, name = "d" });
var c = list.Select(b=> new {b.id, b.name});
var d = list1.Select(b => new { b.id, b.name });
var merge = c.Concat(d).Distinct().ToList();
foreach (var item in merge)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
var list1 = new[]{new {Id = 1, Name = "a"},new {Id = 2, Name = "b"}, new{Id = 3, Name = "c"}}.ToList();
var list2 = new[]{new {Id = 1, Name = "a"},new {Id = 2, Name = "b"}, new{Id = 3, Name = "c"}}.ToList();
list1.AddRange(list2);
Then list1 is the merged list.
You can use the "AddRange" or "Union" or "Concat" functions of c#
e.g
var list1 = new[]{new {Id = 1, Name = "a"},new {Id = 2, Name = "b"}, new{Id = 3, Name = "c"}}.ToList();
var list2 = new[]{new {Id = 1, Name = "a"},new {Id = 2, Name = "b"}, new{Id = 3, Name = "c"}}.ToList();
then
var MergedResult = list1.Union(list2).ToList();
or
var MergedResult = list1.AddRange(list2).ToList();
also you can use Concat as well...
see the difference amongst them here .NET List Concat vs AddRange
I am trying to write a linq query to make a very basic join. I have two arrays
Park[] parks = new Park[]{
new Park() {ID = 1, Name = "Free Park"},
new Park() {ID = 2, Name = "Cost Park"},
new Park() {ID = 3, Name="Sneak in Park"}
};
and
Facility[] facilities = new Facility[] {
new Facility() { ID = 1, Name = "Swing", MinimumAge = 1, MaximumAge = 120},
new Facility() { ID = 2, Name = "Slide", MinimumAge = 1, MaximumAge = 200},
new Facility() { ID = 3, Name = "See-Saw", MinimumAge = 1, MaximumAge = 300}
};
Each park can have 0...n facilities, hence we have a set of mapping objects
ParkFacility[] associations = new ParkFacility[] {
new ParkFacility() {ParkID = 1, FacilityID = 1},
new ParkFacility() {ParkID = 1, FacilityID = 2},
new ParkFacility() {ParkID = 1, FacilityID = 3},
new ParkFacility() {ParkID = 2, FacilityID = 1},
new ParkFacility() {ParkID = 3, FacilityID = 2}
};
This is the definition of the class Park
class Park
{
public int ID { get; set; }
public String Name { get; set; }
public Facility[] Facilities { get; set; }
}
Is it possible to use only joins and associate the appropriate facilities to the parks? i.e. set the Facilities array in Park to be those appropriately mapped using the associations?
Edit: My research thus far..
var x_temp = from g in parks
join j in associations on g.ID equals j.ParkID into h
select new Park()
{
Name = g.Name,
ID = g.ID,
Facilities = (from u in h join m in facilities on u.FacilityID equals m.ID select m).ToArray()
};
I tried using a sub-linq query and it works, but I am looking for a solution with only joins
You can create a lookup from park id to facilities, and use this to populate the Facilities property on each of your Park objects. Note that the best place to do this is in the constructor of Park, but in keeping with your existing code this snippet will do it in the object initializer:
var lookup = associations.ToLookup(pf => pf.ParkID, pf => facilities.Single(f => f.ID == pf.FacilityID));
Park[] parks = new Park[]{
new Park() {ID = 1, Name = "Free Park", Facilities = lookup[1].ToArray()},
new Park() {ID = 2, Name = "Cost Park", Facilities = lookup[2].ToArray()},
new Park() {ID = 3, Name="Sneak in Park", Facilities = lookup[3].ToArray()}
};
Additionally, it would be helpful to store all your Facility and Park instances in a Dictionary mapping the ID to the instance. In that case your lookup wouldn't need to do a linear scan through the all the facilities for each association.