-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add additional Zip
and Unzip
methods
#48
base: master
Are you sure you want to change the base?
Conversation
Also adjusts `ZipImpl` and the other Zip overloads to account for this usage.
/// <param name="secondSelector">A function for selecting the second return sequence's elements from the source sequence's elements.</param> | ||
/// <returns>A tuple of sequences, separating the source sequence according to the selector arguments.</returns> | ||
[SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1414:Tuple types in signatures should have element names", Justification = "By design.")] | ||
public static (IEnumerable<T1>, IEnumerable<T2>) Unzip<TSource, T1, T2>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I can imagine a "lazy" implementation that returns a tuple of two objects that only enumerate the source
sequence as they are enumerated, it seems unlikely that we'd build that. I'm wondering whether it would just be worth returning (IReadOnlyList<T1>, IReadOnlyList<T2>)
since the sequences will be materialised.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this more, a lazy implementation could be Unzip(source, firstSelector, secondSelector) => (source.Select(firstSelector), source.Select(secondSelector)
; I'm wondering if that should just be the implementation, since it adds the benefit of laziness (and just depending on framework code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does enumerate source
twice, which may be undesirable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overriding my earlier comments: Let's keep the signature (to allow for future laziness) and the current implementation (which enumerates source
once).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that you mention it, that gives me an idea: what if we enumerate the source once at the beginning of the method, then return the .Select
results as you mentioned? Then half of the process can be lazy, at least.
var enumeratedSource = source.ToArray();
return (enumeratedSource.Select(firstSelector), enumeratedSource.Select(secondSelector));
I've made that change in a1bfb97
—let me know if that looks good. 👍🏼
In that case, would it be good to make the source
parameter an IReadOnlyCollection
instead, to make the required enumeration clearer to the caller? Or is keeping it an IEnumerable
worth the flexibility? Maybe we could just add a remark to the doc comment that this enumerates source
before the unzipping operation.
Co-authored-by: Dave Dunkin <[email protected]>
So that the unzip operation itself can be lazy.
var enumeratedSource = source?.ToArray() ?? throw new ArgumentNullException(nameof(source)); | ||
return ( | ||
enumeratedSource.Select(firstSelector ?? throw new ArgumentNullException(nameof(firstSelector))), | ||
enumeratedSource.Select(secondSelector ?? throw new ArgumentNullException(nameof(secondSelector))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I remove these ?? throw new ArgumentNullException
s since ToArray
and Select
already throw the same thing for null
arguments? Or is it better to add the throw at this level, too?
Happy Hackoberfest! 😅
I had the desire to unzip one sequence into three in a recent case, so I was wondering, would a three-way
Zip
and two- and three-wayUnzip
s be worthy additions toEnumerableUtility
?A summary of new methods added:
I didn't add a two-way
Zip
with aresultSelector
parameter because one of those was already included in .NET Standard 2.0.