0

I have a class that looks like this:

 public class HistoryViewModel
    {
        [Display(Name="Name")]
        public string ItemName { get; set; }

        [Display(Name="Original Path")]
        public string ItemPath { get; set; }

        [Display(Name="Type")]
        public string ItemType { get; set; }

        [Display(Name="Author")]
        public string EventAuthorName { get; set; }

        [Display(Name="Comment")]
        public string EventActionDesc { get; set; }

        [Display(Name="Timestamp")]
        public DateTime DateOfEvent { get; set; }

        [Display(Name="Action Type")]
        public string ActionType { get; set; }
    }

I have made a list of lists that looks like this:

List<List<HistoryViewModel>> historyRecord = new List<List<HistoryViewModel>>();

After that I fill my historyRecord with some lists by:

historyRecord.Add(new List<HistoryViewModel>{bla bla});

where bla bla are properties of original class HistoryViewModel.

I would like to sort my list of lists by date property but it does not sort my items inside list of lists if they differ only in date.

Here is sorting part:

historyRecord.Sort((x,y) => -1 * x[0].DateOfEvent.CompareTo(y[0].DateOfEvent));

I get sth that looks like this:

Type    Name    Path    Action  Date    Author  Comment
FOLDER  Test    C:\Workspace\Posao\BSM\Storage\LLLL\TTT     CREATE  21.1.2015. 10:24:05     
FILE    76.png  C:\Workspace\Posao\BSM\Storage\abcd\ZZZ     CREATE  21.1.2015. 10:18:58         
FOLDER  ZZZ     C:\Workspace\Posao\BSM\Storage\abcd     CREATE  21.1.2015. 10:07:42     
FOLDER  Test 2  C:\Workspace\Posao\BSM\Storage\abcd     CREATE  21.1.2015. 9:41:56  
FOLDER  Test 2  C:\Workspace\Posao\BSM\Storage\abcd     DELETE  21.1.2015. 9:42:12  
FILE    ZahtjeviZaPromjenu.xlsx     C:\Workspace\Posao\BSM\Storage\abcd\Testni  CREATE  21.1.2015. 8:43:10      
FILE    ZahtjeviZaPromjenu.xlsx     C:\Workspace\Posao\BSM\Storage\abcd\Testni  DELETE  21.1.2015. 9:06:45  
FILE    credentials.txt     C:\Workspace\Posao\BSM\Storage\abcd\Testni  CREATE  21.1.2015. 8:40:58      Uplodao Credentials za test
FILE    credentials.txt     C:\Workspace\Posao\BSM\Storage\abcd\Testni  DELETE  21.1.2015. 8:50:01      Deletano
FILE    credentials.txt     C:\Workspace\Posao\BSM\Storage\abcd\Testni  CREATE  21.1.2015. 9:10:14  
FILE    credentials.txt     C:\Workspace\Posao\BSM\Storage\abcd\Testni  DELETE  21.1.2015. 9:13:28      
FILE    credentials.txt     C:\Workspace\Posao\BSM\Storage\abcd\Testni  CREATE  21.1.2015. 10:07:50     

So, Test 2 and credentials are not sorted correctly as the dates for them don't go descending but random.

How do I sort first: items inside the inner lists and second:lists inside the big list and all that based on date?

Antun Tun
  • 1,507
  • 5
  • 20
  • 38
  • 4
    You are only sorting the list of lists, not the list inside the list of lists. It's not really clear what you are trying to achieve here or what the input was to give the output you got. – Matt Burland Jan 21 '15 at 14:05
  • Thanks, I added a line at the end. – Antun Tun Jan 21 '15 at 14:14
  • 2
    I think `foreach(var record in historyRecord) { record.sort(...) }` is what you want. Of cause it would be nice if it where an `apply( )` linq operator, but there isn't in the standard library. But you can make one and then call `historyRecord.Apply(x => x.Sort(...))` – Vegar Jan 21 '15 at 14:15
  • Or use PLINQ: `historyRecord.AsParallel().ForAll(x => x.Sort(....))`... – Vegar Jan 21 '15 at 14:17
  • As @Vegar said, you'll need to loop through the outer list and call `Sort` on the inner lists. Then you can call sort on the outer list and compare the first items as you were. This won't, however, put everything in order if the range of the inner lists overlap. If you want everything sorted, then you are going to need to flatten your list first and then sort (`SelectMany` might help here). – Matt Burland Jan 21 '15 at 14:17
  • @Vagar I write : historyRecord.AsParallel().ForAll(x => x.Sort((a, b) => -1 * a[0].DateOfEvent.CompareTo(b[0].DateOfEvent))); and it says:Cannot apply indexing with [] to an expression of type 'LaneWebApp.Models.HistoryViewModl' – Antun Tun Jan 21 '15 at 14:26
  • thats because `a` and `b` now are `HistoryViewModel`s not `List`. Or said in another way; Before, you sorted a list of lists. Now you sort each individual list. – Vegar Jan 21 '15 at 14:32
  • But I would like to order my items completely by date, without any grouping of items? This solution groups my inner items, that does not allow sorting by date fully. – Antun Tun Jan 21 '15 at 14:50

2 Answers2

4

It's not entirely clear what you want, but I think you might be able to use something like this:

var sortedRecords = historyRecord
                       .SelectMany(record => record)
                       .OrderBy(record => record.DateOfEvent);

That should give you a single list of all items, ordered by the date.

Edit: And if you want the order reversed...

.OrderByDescending(record => record.DateOfEvent);
Kjartan
  • 18,591
  • 15
  • 71
  • 96
  • I'll try and let you know. Thanks – Antun Tun Jan 21 '15 at 14:30
  • 1
    By using `Sort( )` you actually reorder the items in the list. By using `OrderBy( )`, you get a new `Enumerator` that returns items in order. I think this is a good solution, but if you are going to iterate over the events multiple times, it might be better to do an actual sort. – Vegar Jan 21 '15 at 14:37
  • I need to cast sortedRecords to historyRecords so will let you know. – Antun Tun Jan 21 '15 at 14:47
3

It is not clear what you are trying to achieve exactly. Let's simplify the problem to a List<List<int>>:

What should the output of this list of lists be?: {{1, 2, 5}, {2, 1, 7}, {0, 5, 3}}

  1. Should it be a single flattened list sorted by its elements?

    {0, 1, 1, 2, 2, 3, 5, 5, 7}

  2. Should it be a list of sorted lists sorted by elements of each list?

    {{0, 3, 5}, {1, 2, 5}, {1, 2, 7}}

  3. Something else?

The first case is easily solvable with SelectMany:

List<List<int>> listOfLists = 
                  new List<List<int>> { 
                        new List<int> { 2, 1, 7 }, 
                        new List<int> { 0, 5, 3 }, 
                        new List<int> { 1, 2, 5 } };

var sorted = listOfLists.SelectMany(l => l).OrderBy(l => l);
Console.WriteLine(string.Join(" ", sorted));

In the second case, you'd need to iterate first to sort all your lists:

List<List<int>> listOfLists = new List<List<int>> { 
                        new List<int> { 1, 2, 5 }, 
                        new List<int> { 2, 1, 7 }, 
                        new List<int> { 0, 5, 3 } };

foreach (var list in listOfLists)
{
    list.Sort();
}

var sorted = listOfLists.OrderBy(l => l.First());

foreach (var list in sorted)
{
    Console.WriteLine(string.Join(" ", list));
}
Kjartan
  • 18,591
  • 15
  • 71
  • 96
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • Thank you for your time, you got it right but the solution selected is more elegant so I had to choose one. – Antun Tun Jan 21 '15 at 15:03