6
\$\begingroup\$

Can you find a more understandable way to write the following one-liner?

Enumerable.Range(0, relation.Fields.Count).
           Any(i => relation.Fields[i] != relation.ForeignFields[i])

but still preserving its brevity?

Simply put, I wanna cycle on relation.Fields collection to see if their string elements are one-by-one equal to relation.ForeignFields ones.

The reason I had to use Enumerable.Range is that I need an index, in order to cycle the two collections.

Note: they have for sure the same count.


I wrote an extension method based on @t3chb0t's answer

\$\endgroup\$
6
  • 1
    \$\begingroup\$ I have rolled back the last edit. Please see what you may and may not do after receiving answers. \$\endgroup\$
    – Pimgd
    Jul 22, 2016 at 15:57
  • \$\begingroup\$ @Pimgd In spite of my little reputation on CodeReview, I have plenty on StackOverflow and I know how to behave on StackExchange. \$\endgroup\$
    – Teejay
    Jul 22, 2016 at 15:59
  • \$\begingroup\$ @Pimgd The fact is that my edit was not a complete answer, so I didn't post it as a self-answer, but accepted t3chb0t's one instead. \$\endgroup\$
    – Teejay
    Jul 22, 2016 at 16:00
  • 2
    \$\begingroup\$ That's great. We have slightly different rules here, please read them. What you did was not so much wrong as that it risks reviewers reviewing your newly added code, which creates a problematic cycle as some answers refer to revision 1 and others to revision 2. Thus we rollback - not because it is wrong to want to say what you did, but to prevent reviewers from wasting their time. \$\endgroup\$
    – Pimgd
    Jul 22, 2016 at 16:00
  • 2
    \$\begingroup\$ one option would be post a self answer (with reasoning included, not just a code dump), link to it in the question, leave the accept as is \$\endgroup\$
    – Pimgd
    Jul 22, 2016 at 16:04

3 Answers 3

7
\$\begingroup\$

This is not realy shorter then your example but it will work with any enumerable and does not require a count/length to be known:

var any = Fields
    .Select((field, i) => new { filed, i })
    .Any(x => x.field != relation.ForeignFields[x.i])

I think this might work as well if both collections are in sync:

var any = Fields.Zip(relation.ForeignFields, (x, y) => x != y).Any(z => z);
\$\endgroup\$
13
  • 1
    \$\begingroup\$ Unfortunately, AFAIK, Any does not support index as second lambda parameter, only Select does. \$\endgroup\$
    – Teejay
    Jul 22, 2016 at 15:19
  • \$\begingroup\$ Ok, now that you've edited the answer, it's ok. \$\endgroup\$
    – Teejay
    Jul 22, 2016 at 15:21
  • \$\begingroup\$ @Teejay I thought it would so I checked it and fixed the example. \$\endgroup\$
    – t3chb0t
    Jul 22, 2016 at 15:21
  • \$\begingroup\$ @Teejay I noticed it at the same time as you've commented ;-) \$\endgroup\$
    – t3chb0t
    Jul 22, 2016 at 15:21
  • \$\begingroup\$ Ok, anyway I was looking for something even easier, but probably you're right when saying that "this is the shortest"... \$\endgroup\$
    – Teejay
    Jul 22, 2016 at 15:23
9
\$\begingroup\$

Can you not simply do SequenceEqual?

var list = new List<string> { "test1", "test2", "test3" };
var list2 = new List<string> { "test1", "test2", "test3" };

var areListsEqual = list.SequenceEqual(list2);
\$\endgroup\$
7
  • 1
    \$\begingroup\$ @Hosch250 it (code by asker) seems to check if any not matches - so if all match. \$\endgroup\$
    – Pimgd
    Jul 22, 2016 at 16:13
  • \$\begingroup\$ Thanks, dindn't know about this one. I'll use it for the particular case. This wouldn't be applicable if the lambda condition was different though, so my accepted answer will remain the current one. Anyway, I upvoted. \$\endgroup\$
    – Teejay
    Jul 22, 2016 at 16:14
  • \$\begingroup\$ Ah, right. Removed my comment. \$\endgroup\$
    – user34073
    Jul 22, 2016 at 16:15
  • \$\begingroup\$ If you wanted to play with the elements afterward, you can also do list.Except(list2) or vice versa. \$\endgroup\$ Jul 22, 2016 at 16:17
  • \$\begingroup\$ This also has a different meaning than the example in @Teejay's question. The original code checks whether Fields is a prefix of ForeignFields, not whether they're equal. \$\endgroup\$ Jul 22, 2016 at 20:25
3
\$\begingroup\$

Based on @t3chb0t's answer, I ended up writing an extension method Any that also provides indexing:

public static bool Any<T>(this IEnumerable<T> enumerable, Func<T, int, bool> lambda)
{
    return enumerable.Select((el, ix) => new { el, ix }).Any(x => lambda(x.el, x.ix));
}

Use:

relation.Fields.Any((f, ix) => f != relation.ForeignFields(ix))

That way, code in the main software remains concise and understandable.


I wrote an All version as well:

public static bool All<T>(this IEnumerable<T> enumerable, Func<T, int, bool> lambda)
{
    return enumerable.Select((el, ix) => new { el, ix }).All(x => lambda(x.el, x.ix));
}
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.