0

I am trying to make an extension method and am having some difficulty with this case, examples:

IEnumerable<string> list1 = // { "A", "B", "C" }
IEnumerable<string> list2 = // { "B", "D" }
IEnumerable<string> list3 = // { "D", "A", "C". "B" } 

list1.OrderByEnumerable(list3) -> // { "A", "C", "B" }
list2.OrderByEnumerable(list3) -> // { "D", "B" } 

I have been trying something along the lines of:

static IEnumerable<T> OrderByEnumerable<T>(this IEnumerable<T> data, IEnumerable<string> data2)
{
    return data.Zip(data2, (x, y) => //
}

but I quickly realized I need some way to iterate through the enumerables to find out of I need to "skip" a value and somehow. Any ideas or pointers in the right direction?

dev way
  • 71
  • 6
  • 1
    What is expected result in case when item not exists in `list3`? – Fabio Aug 30 '17 at 02:30
  • If you are willing to work with lists, instead of IEnumerable, [here](https://stackoverflow.com/a/15275394/6741868) is a one line answer which might help you. – Keyur PATEL Aug 30 '17 at 02:35
  • 1
    @Fabio yes your question is valid and unless or until the OP answers it, it is hard to post an answer because I do not know what to do in that case either so I am holding off. Better yet, I am going to go to sleep :) – CodingYoshi Aug 30 '17 at 03:33
  • Sorry, list 3 is the list that is going to be the 'order' list1 and list2 must follow, if list3 has a object not in list1 or list2, it is skipped – dev way Aug 30 '17 at 03:48
  • So if list 1 or 2 has something list 3 doesnt have, probably should break or return original list, if list 3 has something 1 or 2 doesnt have, it is skipped. As long as 1 and 2 follow the ordering pattern set forth by 3 for all matching items – dev way Aug 30 '17 at 03:49

2 Answers2

3

In looking at this example:

list1.OrderByEnumerable(list3) -> // { "A", "C", "B" }

...I can't help but notice that the list is exactly the same as list3 with items removed if they do not appear in list1.

So maybe you just need to intersect and be done:

list3.Intersect(list1) -> // { "A", "C", "B" }

Of course it is always possible that list1 contains some items that aren't in list3, but you didn't specify a requirement in that case. I guess you could just add them to the end:

list3.Intersect(list1).Union(list1.Except(list3)); -> // { "A", "C", "B" }

This is equivalent to what you are attempting, without any need to Zip or Join anything.

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • `list3.Intersect(list1)` will produce `{ "A", "B", "C" }` not `{ "A", "C", "B" }`. This is not what the question is asking but the OP has accepted it so perhaps the question is wrong. – CodingYoshi Aug 30 '17 at 02:47
  • @CodingYoshi, in case where `{ "D", "A", "C". "B" }` ordered by `{ "A", "B", "C" }` result should be `{ "A", "B", "C" }`, only mystery is still what to do when `"D"` not exists in "order" collection – Fabio Aug 30 '17 at 03:12
  • I misunderstood, Both of you are correct in those cases. – dev way Aug 30 '17 at 03:21
0
public static IEnumerable<T> OrderByEnumerable<T>(this IEnumerable<T> data,
                                                       IEnumerable<T> data2)
{
    return data.Except(data2).Any() ? data : data2.Join(data, _ => _, _ => _, (_, __) => _);
}
Andriy Tolstoy
  • 5,690
  • 2
  • 31
  • 30