nuclear sweet
nuclear sweet

Reputation: 1121

Sort collection by another collection values

I have List<SomeData> data;

public class SomeData
{
    public int Key { get; set;}
    public decimal Value { get; set;}
}

Also i have List<int> DataOrder;

I need to sort List<SomeData>data by Key, placing it in same order as List<int> DataOrder values.

Is there any common algorithms for that?

Example:

List<SomeData> data = new List<SomeData>();
data.Add(new SomeData{ Key = 10, Value = 14 })
data.Add(new SomeData{ Key = 25, Value = 22 })
data.Add(new SomeData{ Key = 567, Value = 3 })
data.Add(new SomeData{ Key = 57, Value = 300 })
data.Add(new SomeData{ Key = 17, Value = 200 })
data.Add(new SomeData{ Key = 343, Value = 42 })

List<int> DataOrder = new List<int>{1, 25, 700, 567, 343, 350, 10};

Result after sorting:

foreach(var element in data)
{
     Console.WriteLine(element.Key);
}

Out:

25
567
343
10
57
17

Edit: initial data array can have Key, that not contain in DataOrder Such value should be placed at the end of result collection in any order. Example changed to illustrate it.

Upvotes: 2

Views: 145

Answers (3)

isxaker
isxaker

Reputation: 9446

Solved

public class SomeData
{
    public int Key { get; set; }
    public decimal Value { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        List<SomeData> orders = new List<SomeData>();

        orders.Add(new SomeData { Key = 10, Value = 14 });
        orders.Add(new SomeData { Key = 25, Value = 22 });
        orders.Add(new SomeData { Key = 567, Value = 3 });
        orders.Add(new SomeData { Key = 57, Value = 300 });
        orders.Add(new SomeData { Key = 17, Value = 200 });
        orders.Add(new SomeData { Key = 343, Value = 42 });

        List<int> ids = new List<int> { 1, 25, 700, 567, 343, 350, 10 };

        //get orders only from ids with order
        List<SomeData> existedOrders = (from order in orders
                                        join id in ids
                                             on new { onlyId = order.Key }
                                            equals new { onlyId = id }
                                        orderby ids.IndexOf(id)
                                        select order).ToList();

        //add others
        existedOrders.AddRange(orders.Except(existedOrders).ToList());

    }
}

//with @HimBromBeere solution you can reduce query

//get orders only from ids with order
List<SomeData> existedOrders = (from order in orders
                                join id in ids
                                     on order.Key equals id
                                orderby ids.IndexOf(id)
                                select order).ToList();

Upvotes: 1

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37000

What about joining:

var mySortedList = (from i in DataOrder
            join d in data on i equals d.Key
            select new SomeData 
            { 
                Key = d.Key, 
                Value = d.Value 
            });

EDIT: To also add those values from data that do NOT share any key within the DataOrder-list you may simply add a Union to the result as follows:

var result = mySortedList.Union(data.Where(x => !DataOrder.Contains(x.Key)));

Upvotes: 2

darson1991
darson1991

Reputation: 406

int count = 0;
for(int i in DataOrder)
{
    var index = data.IndexOf(d => d.Key == i);
    swap(data[count], data[index]);
    count++;
}

and swap function is for swap places of items.

Upvotes: 0

Related Questions