0

I have a list like:

| Name | number | order |  
|------|--------|-------|
| rt   | 7432   | down  |
| ht   | 2000   |  up   |
| hr   | 2730   |  up   |   
| cc   | 1000   | down  |
| af   | 1430   | down  |  
| ge   | 3000   |  up   |
| bb   | 4800   | down  |
| ke   | 1200   |  up   |
| wd   | 1100   |  up   |

what i need to do is to sort this list like:

| name | number | order |
|------|--------|-------|
| ge   |  3000  |  up   |
| hr   |  2730  |  up   |
| ht   |  2000  |  up   |
| ke   |  1200  |  up   |
| cc   |  1000  | down  |
| wd   |  1100  |  up   |
| af   |  1430  | down  |
| bb   |  4800  | down  |
| rt   |  7432  | down  |
  • Note
    1. the list is divided into two groups "up" and "down"
    2. the "number" column is ordered based on : high, middle, low/low, middle, high
    3. Regardless of the "up" and "down" grouping, the lowest number should be in the middle, when the number of rows are odd and one of the middle rows when the rows are even.

are there any efficient way of creating this new list without having to check every row and placing it into the new list !!??

your input is greatly appreciated

Mehrdad_gh
  • 33
  • 2
  • 11

1 Answers1

1

Overall, having to place the "middle" element is the most problematic here. Otherwise it would be easy to implement IComparer or simply use linq for it.

Still, you don't have to check every value manually. I don't think the below linq code is optimal, but it's fairly simple. I used MinBy implementation provided here to get the minimal object and Tuple to not implement classes:

        List<Tuple<string,int,string>> list = new List<Tuple<string,int,string>>();
        list.Add(Tuple.Create<string, int, string>("a",100,"up"));
        list.Add(Tuple.Create<string, int, string>("b",99,"up"));
        list.Add(Tuple.Create<string, int, string>("c",120,"up"));
        list.Add(Tuple.Create<string, int, string>("d",200,"up"));

        list.Add(Tuple.Create<string, int, string>("e",112,"down"));
        list.Add(Tuple.Create<string, int, string>("f",10,"down"));
        list.Add(Tuple.Create<string, int, string>("g",110,"down"));

        var temp=list.ToLookup(x => x.Item3);

        var up = temp["up"].OrderByDescending(a => a.Item2);
        Tuple<string, int, string> lowestUp = up.MinBy(a => a.Item2);

        var down=temp["down"].OrderBy(a => a.Item2);
        Tuple<string, int, string> lowestDown = down.MinBy(a => a.Item2);

        if (lowestDown.Item2 < lowestUp.Item2)
        {
            var result = up.Union(down.Except(new Tuple<string, int, string>[] { lowestDown })).ToList();
            result.Insert(result.Count / 2, lowestDown);
        }
        else
        {
            var result = up.Except(new Tuple<string, int, string>[] { lowestUp }).Union(down).ToList();
            result.Insert(result.Count / 2, lowestUp);
        }

EDIT: I interepreted "middle" as the element with index count/2.

Arie
  • 5,251
  • 2
  • 33
  • 54
  • Thank you very much for your input, but MoreLinq does not seem to like my system, although i have already added it to my references but it will not show up when trying to make a reference :) i am using .net 4.51 and the project is a console app !! any ideas why !!? – Mehrdad_gh Mar 23 '17 at 15:30
  • @Mehrdad_gh I did not use the library, I just copied the implementation of the MinBy extension method provided in this answer http://stackoverflow.com/a/914198/891715 – Arie Mar 24 '17 at 07:58
  • Thank you for your feedback, i did overcome the problem with the installation of the library, and tested your suggested code. it looks as if your code works only when the number "up" and "down" filters are equal or perhaps differ by one, but when this pattern changes it will only sort the top and bottom parts correctly, meaning high, middle (in the upper part) and high, middle (in the bottom part) are placed correctly, while the low sides are some how messed up. any suggestions !!? – Mehrdad_gh Mar 24 '17 at 12:06