user2423609
user2423609

Reputation: 85

Linq on string array

string[] listOne = new string[] { "dog", "cat", "car", "apple"};
string[] listTwo = new string[] { "car", "apple"};

What I need is to order listOne by the order of items in listTwo(if present). So the new list would be in this order:

"car", "apple", "dog", "cat"

Upvotes: 1

Views: 6131

Answers (6)

Damith
Damith

Reputation: 63065

var result = listTwo.Union(listOne);

OR

var result =listTwo.Intersect(listOne).Concat(listOne.Except(listTwo));
var result = listTwo.Where(listOne.Contains).Concat(listOne.Except(listTwo));

First answer posted has bug with listTwo item order, please neglect below answer

var result = listOne.OrderBy(i => !listTwo.Contains(i)).ToList();

result

"car", "apple", "dog", "cat"

Upvotes: 3

Squid
Squid

Reputation: 4810

This works, but I have a feeling it could be done better:

var result=
    from item in listOne
    let existsInListTwo=listTwo.Contains(item)
    let positionInListTwo=Array.IndexOf(listTwo, item)
    orderby !existsInListTwo, positionInListTwo
    select new {
        Item=item,
        position=positionInListTwo,
        exists=existsInListTwo
    };

Edit: Using a combination of this and Damith's approach this is a little more readable:

var result=
    listOne.OrderBy(i => !listTwo.Contains(i))
           .ThenBy(i => Array.IndexOf(listTwo, i))
           .ToList();

Upvotes: 0

MeTitus
MeTitus

Reputation: 3428

var result = listOne.Union(listTwo)
            .Distinct()
            .OrderBy(i => !listTwo.Contains(i));

Upvotes: 0

Ken Kin
Ken Kin

Reputation: 4683

Since you are using arrays, most of the use of linq, will create a new instance of some kind of IEnumerable, for example, ToList or ToArray.

Thus I'd suggest that to use Array.Sort with Comparison:

string[] listOne=new string[] { "dog", "cat", "car", "apple" };
string[] listTwo=new string[] { "car", "apple" };

Comparison<String> comparison=
    (x, y) => {
        if(!listTwo.Contains(x)||!listTwo.Contains(y))
            return 0;
        else {
            var indexOfX=Array.IndexOf(listTwo, x);
            var indexOfY=Array.IndexOf(listTwo, y);
            return indexOfX.CompareTo(indexOfY);
        }
    };

Array.Sort(listOne, comparison);

It would be sorted with quick sort algorithm internally, it's an in-place algorithm.

Upvotes: 2

David
David

Reputation: 16277

var sub1 = listOne.Intersect(listTwo).ToList();
var sub2 = listOne.Except(listTwo); 
sub1.AddRange(sub2);

enter image description here

Upvotes: 2

cat916
cat916

Reputation: 1361

You can use extension method Union()

var result = listTwo.Union<string>(listOne);

Upvotes: 3

Related Questions