1
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"

2
  • 1
    You don't need linq. Just loop through second list and if the value there is matched by the first list add that value to the sorted list and remove it from the source list. Then add all remaining elements in the source list to the sorted list. Commented May 27, 2013 at 3:42
  • 1
    what you recommend is exactly linq good at. Commented May 27, 2013 at 3:45

6 Answers 6

3

You can use extension method Union()

var result = listTwo.Union<string>(listOne);
Sign up to request clarification or add additional context in comments.

3 Comments

Where is the intersection the op asked?
Union extension method would be the same as Union two sets in terms of mathematic. Union set would consists of intersection. The result is the same.
The explicit of the type of generics can be omitted: listTwo.Union(listOne). I guess this answer is most applicable.
3
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"

3 Comments

Would this work if listTwo was : { "apple", "car" } wouldn't it return the items in the same order as they appear in listOne?
A combination of your approach and mine would solve the question I raised: var result = listOne.OrderBy(i => !listTwo.Contains(i)).ThenBy(i => Array.IndexOf(listTwo,i)).ToList(); an probably look a lot simpler than my approach.
@Squid: If listTwo was { "apple", "car" }, the code in this answer outputs an array of { "car", "apple", "dog", "cat" }.
2
var sub1 = listOne.Intersect(listTwo).ToList();
var sub2 = listOne.Except(listTwo); 
sub1.AddRange(sub2);

enter image description here

Comments

2

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.

4 Comments

I believe the focus here was to get something simple for the OP
@Marco: ah .. is this not simple .. ?
@Marco: But the currently highest voted answer outputs with an incorrect result if the order in listTwo changes ..
But that is what the OP what, otherwise we would have said a ordered list two.
0
var result = listOne.Union(listTwo)
            .Distinct()
            .OrderBy(i => !listTwo.Contains(i));

Comments

0

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();

4 Comments

changing to let existsInListTwo = (positionInListTwo != -1) would avoid a second enumeration of listTwo.
It is not better than the existing options provided, it is actually actually the worst option and the most complicated to read.
Marco - but to my mind it is the only one that solves the question OP asked. If you were to change the order of the items in listTwo, none of the other answers would order results in the order they appear in listTwo, they simply bubble results that are in listTwo to the top.
But is the least readable, and that is important as well and are you sure the OP asked that; I can't understand the question myself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.