king jia
king jia

Reputation: 712

Sorting a list based on another attribute in another list

I have the objects as below:

public class CustomerSequence
{
    public string CustomerName  { get; set; } 
    public int Sequence { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Component { get; set; } 
}

Let's say I have 2 Lists Object

Customer:                             CustomerSequence:
Id         Name        Component      CustomerName         Sequence
1          AAA         AAAAAA         AAA                  2
2          BBB         BBBBBBB        BBB                  4
3          CCC         CCCCC          CCC                  1
                                      DDD                  3

As you can see there is no DDD in List.

I want to sort the List Customer based on the List CustomerSequence

Result is:

Customer:
Id         Name        Component
3          CCC         CCCCC
1          AAA         AAAAAA
2          BBB         BBBBBBB        

Anyone can help me please.

Upvotes: 1

Views: 76

Answers (4)

Nitin Varpe
Nitin Varpe

Reputation: 10694

Use Join

var customers = from cust in Customer
                     join cust_seq in CustomerSequence
                     on cust.Name equals cust_seq.CustomerName         
                     orderby cust_seq.Sequence
                     select cust;

Upvotes: 1

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236268

Join both sequences on customer name, then order by sequence value:

from c in customers
join cs in customerSequences
    on c.Name equals cs.CustomerName
orderby cs.Sequence
select c;

Lambda syntax is not that beautiful, and it will look like

customers.Join(customerSequences, 
               c => c.Name, cs => cs.CustomerName, (c,cs) => new { c, cs })
         .OrderBy(x => x.cs.Sequence)
         .Select(x => x.c)

Internally join uses lookup for second sequence, which is much more effective then linear search with Where.


If it is possible that there is no CustomerSequencs matching customer, or there is more than one match, then use group join:

from c in customers
join cs in customerSequences
    on c.Name equals cs.CustomerName into g
orderby g.Select(cs => cs.Sequence).FirstOrDefault() 
select c

This query uses 0 form missing sequences, and first matched value if there is more than one sequence for customer.

Upvotes: 3

Bob Vale
Bob Vale

Reputation: 18474

Try this

Customer.OrderBy(x => CustomerSequence.Where(y => y.CustomerName == x.Name)
                                      .Select(y => y.Sequence)
                                      .FirstOrDefault())

Alternatively you can use a join which would be better if the source was a database

var sorted = 
from c in customer
join csj in customerSequence on c.Name equals csj.CustomerName into customerSequenceJoined
from cs in customerSequenceJoined.DefaultIfEmpty()
orderby cs == null ? 0 : cs.Sequence
select c;

The cs == null ? 0 : cs.Sequence deals with the case when there is no matching record in the sequence collection. You could use int.MaxValue if you want these items to appear last.

Upvotes: 2

Enigmativity
Enigmativity

Reputation: 117134

I tend to use a dictionary for this sort of thing.

var customerSequence =
    customerSequences
        .ToDictionary(x => x.CustomerName, x => x.Sequence);

var sortedCustomers = 
    customers
        .OrderBy(x => customerSequence[x.Name])
        .ToList();

Upvotes: 0

Related Questions