Home > Net >  Efficent way List order by element index
Efficent way List order by element index

Time:09-24

I have a List of Books which below :

List<book> books = new List<book>() 
{ 
    new() { bookName = "wingbook" }, 
    new() { bookName = "Peter Pan" },
    new() { bookName = "Apple Pie" },
    new() { bookName = "Zebra" } 
}

I want to find way to order by books by index descending order (not a book name). Expected result is

result = {
    { bookName = "Zebra" },
    { bookName = "Apple Pie" },
    { bookName = "Peter Pan" },
    { bookName = "wingbook" }
}

Can I know how to write it simplified it ?

CodePudding user response:

You simply want to reverse the list? Then use:

books.Reverse();

or you could use the Reverse extension method, that does not modify the original collection:

var ordered = books.AsEnumerable().Reverse();

You could also use the Select overload to get the index:

books = books 
    .Select((book, index) => (book, index))
    .OrderByDescending(x => x.index)
    .Select(x => x.book)
    .ToList();

CodePudding user response:

Define an index or id field to books for order:

List<book> books = new List<book>() 
{ 
    new() { index = 0, bookName = "wingbook" }, 
    new() { index = 1, bookName = "Peter Pan" },
    new() { index = 2, bookName = "Apple Pie" },
    new() { index = 3, bookName = "Zebra" } 
}

var result = books.OrderByDescending(x => x.index).ToList();

CodePudding user response:

I typically need to use fix indexing also and i have made a simple generic Class with a converter extension so that it can convert any List<>.

This is the indexed collection item class which contains the index, the item and also tells if it's the first or last index no matter the sorting.

public class IndexedCollection<T>
{
    public int Index { get; private set; }
    public T Value { get; private set; }

    private int Count { get; set; }
    public bool IsFirst { get { return Index == 0; } }
    public bool IsLast { get { return Index == Count - 1; } }

    public IndexedCollection(T value, int index, int count)
    {
        Value = value;
        Index = index;
        Count = count;
    }
}

a simple conversion extension look like this :

public static List<IndexedCollection<T>> WithIndex<T>(this List<T> list)
{
    var count = list.Count;

    return list.Select((value, index) => new IndexedCollection<T>(value, index, count)).ToList();
}

A typical way of using this would be the following based on your sample data :

List<book> books = new List<book>() 
{ 
    new() { bookName = "wingbook" }, // 0 (index it will be given when converted)
    new() { bookName = "Peter Pan" }, // 1
    new() { bookName = "Apple Pie" }, // 2
    new() { bookName = "Zebra" } // 3
}

// convert to List<IndexCollection<Book>>()
// which doesn't required to alter the original object
var indexedBooks = books.WithIndex();

// want to sort by name
indexedBooks = indexedBooks.OrderBy(o => o.Value.bookName).ToList();

// sort again by index desc
indexedBooks = indexedBooks.OrderByDescending(o => o.Index).ToList();    

// want to just return the book objects
var justTheBooks = indexedBooks.Select(o => o.Value).ToList();
  • Related