Reputation: 127
I have a List contains some BW
objects with 2 properties are shape
and quantity
.
Depend on the preShape
value and preQuantity
value has been given, I will sort by each item in List<BW>
with the preShape
and preQuantity
. The shape
is priority first then the quantity
is second priority. I have sorted the List<BW>
with GroupBy
then sort by the shape
and quantity
depends on the preShape
and preQuantity
. The result is fine like this:
| shape | quantity|
--------|----------
| MN22 | 20 |
| MN22 | 14 |
| MN11 | 20 |
| MN11 | 10 |
| ANT | 20 |
| ANT | 18 |
| ANT | 16 |
| ANT | 10 |
But I would like to have List<BW>
like this:
| shape | quantity|
--------|----------
| MN22 | 20 |
| MN22 | 14 |
| MN11 | 10 |
| MN11 | 20 |
| ANT | 20 |
| ANT | 10 |
| ANT | 16 |
| ANT | 18 |
I tried to use for
loop and swap
function for to sort but the result is not like what I'm looking for.
I would like to sort by the List with the result like the 2nd table.
I need to group shape to make them in a group and I will compare shape of each item in List with the pre-shape, if they are match I will sort List with pre-shape then the quantity will be the second condition. But the quantity of the last item in group A must be followed by the same quantity of the first item in group B. If they are not match then the quantity of the first item in group B will be sorted ASC.
I attach my code here for more description my dottnetfiddle code
public static void Main()
{
List<BW> lst = new List<BW>(){
new BW(){ shape = "MN11", quantity = 20},
new BW(){ shape = "MN11", quantity = 10},
new BW(){ shape = "MN22", quantity = 14},
new BW(){ shape = "MN22", quantity = 20},
new BW(){ shape = "ANT", quantity = 16},
new BW(){ shape = "ANT", quantity = 18},
new BW(){ shape = "ANT", quantity = 20},
new BW(){ shape = "ANT", quantity = 10}
};
string preShape = "MN22";
int preQuantity = 20;
var tempList = lst.GroupBy(c=>c.shape).Select(g=> new {shapeGroup = g.Key, BW = g.OrderBy(c=> c.shape.Equals(preShape)).ThenByDescending(c=>c.quantity)}).OrderByDescending(g=>g.shapeGroup.Equals(preShape));
//var tempList = lst.GroupBy(c=>c.shape).Select(g=> new {shapeGroup = g.Key, BW = g.OrderByDescending(c => c.shape.Equals(preShape))}).OrderBy(g=>g.BW.First().quantity == preQuantity);;
foreach (var shape in tempList)
{
var lastGroupBW_Item = shape.BW.LastOrDefault();
//Console.WriteLine("{0}", shape.shape);
foreach (var bw in shape.BW)
{
if(shape.BW.ToList().IndexOf(bw) > 0 )
{
shape.BW.OrderBy(c=>c.quantity == lastGroupBW_Item.quantity).ThenBy(c=>c.quantity);
}
Console.WriteLine("{0}|{1}", bw.shape,bw.quantity);
}
}
}
The last result I would like to have is like the second table I describe above. Thanks in advance!
Upvotes: 0
Views: 301
Reputation: 127
@tymtam's solution is the correct answer for my post. Thanks everyone for the help, I have learnt more trick to use lambda to sort by my list.
Upvotes: 0
Reputation: 35105
I think this follows the specification.
// Order by shape first; the everybody gets it part
var shapeSorted = lst
.OrderBy(bw => bw.shape != preShape)
.ThenByDescending(bw => bw.shape);
// Order gropus by ascending, but if equal to last item in the previous group then first
var currentSpecialQ = preQuantity;
var r = new List<BW>();
foreach(var group in shapeSorted.GroupBy(bw => bw.shape) ) {
r.AddRange(group.OrderBy(bw => bw.quantity != currentSpecialQ).ThenBy(bw => bw.quantity));
currentSpecialQ = r.Last().quantity;
}
MN22, 20
MN22, 14
MN11, 10
MN11, 20
ANT, 20
ANT, 10
ANT, 16
ANT, 18
public class BW
{
public string shape { get; set; }
public int quantity { get; set; }
}
class Program
{
public static void Main(string[] args)
{
List<BW> lst = new List<BW>(){
new BW(){ shape = "MN11", quantity = 20},
new BW(){ shape = "MN11", quantity = 10},
new BW(){ shape = "MN22", quantity = 14},
new BW(){ shape = "MN22", quantity = 20},
new BW(){ shape = "ANT", quantity = 16},
new BW(){ shape = "ANT", quantity = 18},
new BW(){ shape = "ANT", quantity = 20},
new BW(){ shape = "ANT", quantity = 10}
};
string preShape = "MN22";
int preQuantity = 20;
// Order by shape first; the everybody gets it part
var shapeSorted = lst
.OrderBy(bw => bw.shape != preShape)
.ThenByDescending(bw => bw.shape);
// Order gropus by ascending, but if equal to last item in the previous group then first
var currentSpecialQ = preQuantity;
var r = new List<BW>();
foreach(var group in shapeSorted.GroupBy(bw => bw.shape) ) {
r.AddRange(group.OrderBy(bw => bw.quantity != currentSpecialQ).ThenBy(bw => bw.quantity));
currentSpecialQ = r.Last().quantity;
}
foreach(var bw in r ) Console.WriteLine($"{bw.shape}, {bw.quantity}");
}
}
Upvotes: 2
Reputation: 1
string preShape = "MN22";
int preQuantity = 20;
He wants the first value of group MN22 == preQuantity
the first value of group MN11
nearest the last of group MN22
and the first value of group ANT
nearest the last of group MN11
Example:
| MN22 | 14 |
| MN22 | 20 |
| MN11 | 10 |
| MN11 | 20 |
| ANT | 10 |
| ANT | 16 |
| ANT | 18 |
| ANT | 20 |
==>
| MN22 | 20 |
| MN22 | 14 |
| MN11 | 10 |
| MN11 | 20 |
| ANT | 20 |
| ANT | 18 |
| ANT | 16 |
| ANT | 10 |
Upvotes: -1
Reputation: 186813
So items with shape == preShape
should be on the top as well as quantity == preQuantity
; you can sort by bool
for this (note, that false < true
):
List<BW> lst = ...
var result = lst
.OrderByDescending(item => item.shape != preShape) // preShape on the top
.ThenByDescending(item => item.shape) // in case of tie by shape
.ThenByDescending(item => item.quantity != preQuantity) // preQuantity on the top
.ThenBy(item => item.quantity); // in case of tie by quantity
Demo: (I've used Tuple
in order to emulate BW
)
List<(string shape, int quantity)> lst = new List<(string shape, int quantity)>(){
( shape :"MN11", quantity : 20),
( shape :"MN11", quantity : 10),
( shape :"MN22", quantity : 14),
( shape :"MN22", quantity : 20),
( shape : "ANT", quantity : 16),
( shape : "ANT", quantity : 18),
( shape : "ANT", quantity : 20),
( shape : "ANT", quantity : 10),
};
string preShape = "MN22";
int preQuantity = 20;
var result = lst
.OrderByDescending(item => item.shape == preShape) // preShape on the top
.ThenByDescending(item => item.shape) // in case of tie by shape
.ThenByDescending(item => item.quantity == preQuantity) // preQuantity on the top
.ThenBy(item => item.quantity); // in case of tie by quantity
Console.Write(string.Join(Environment.NewLine, result));
Outcome:
(MN22, 20) // preShape is the first to come; preQuantity is on the top within MN22 shape
(MN22, 14)
(MN11, 20) // preQuantity is on the top within the MIN11 shape
(MN11, 10)
(ANT, 20) // preQuantity is on the top within the ANT shape
(ANT, 10)
(ANT, 16)
(ANT, 18)
Upvotes: 7