GithubHelp home page GithubHelp logo

morelinq / morelinq Goto Github PK

View Code? Open in Web Editor NEW
3.6K 112.0 409.0 3.77 MB

Extensions to LINQ to Objects

Home Page: https://morelinq.github.io/

License: Apache License 2.0

C# 99.50% Batchfile 0.24% Shell 0.12% PowerShell 0.14%
linq dotnet

morelinq's Introduction

MoreLINQ

LINQ to Objects is missing a few desirable features.

This project enhances LINQ to Objects with extra methods, in a manner which keeps to the spirit of LINQ.

MoreLINQ is available for download and installation as NuGet packages.

Documentation for the stable and beta releases can be found at morelinq.github.io.

Usage

MoreLINQ can be used in one of two ways. The simplest is to just import the MoreLinq namespace and all extension methods become instantly available for you to use on the types they extend (typically some instantiation of IEnumerable<T>). In some very rare instances, however, doing so can cause conflicts with other libraries you may be using that incidentally also extend the same type with an identically named method and signature. This happened with MoreLINQ, for example, when Microsoft .NET Framework 4.0 introduced Zip and MoreLINQ already had one. Starting with version 3.0 of MoreLINQ, you can reduce the potential for present (or even future) conflicts by individually importing just the extension methods you need using the static imports feature introduced in C# 6:

using static MoreLinq.Extensions.LagExtension;
using static MoreLinq.Extensions.LeadExtension;

In the example above, only the Lag and Lead extension methods will be available in scope.

Apart from extension methods, MoreLINQ also offers regular static method that generate (instead of operating on) sequences, like Unfold, Random, Sequence and others. If you want to use these while statically importing other individual extension methods, you can do so via aliasing:

using static MoreLinq.Extensions.LagExtension;
using static MoreLinq.Extensions.LeadExtension;
using MoreEnumerable = MoreLinq.MoreEnumerable;

In the example above, Lag and Lead will be available as extension methods as well as all the regular static methods on MoreEnumerable but without any of the extension methods offered by MoreEnumerable.

Building

Run either build.cmd if building on Windows or build.sh if building on macOS or a Linux distribution supported by .NET.

Some code in the project is generated using T4 templates. To regenerate the code from modified templates, run MoreLinq\tt.cmd (Windows) or MoreLinq/tt.sh depending on your platform.

Building the documentation is supported on Windows only and requires Sandcastle Help File Builder (SHFB). Executing builddocs.cmd generates the documentation in the docs/api directory. It can be browsed locally using any HTTP server of static files, like dotnet-serve.

Operators

Acquire

Ensures that a source sequence of disposable objects are all acquired successfully. If the acquisition of any one fails then those successfully acquired till that point are disposed.

Aggregate

Applies multiple accumulators sequentially in a single pass over a sequence.

This method has 7 overloads.

AggregateRight

Applies a right-associative accumulator function over a sequence. This operator is the right-associative version of the Aggregate LINQ operator.

This method has 3 overloads.

Append

Returns a sequence consisting of the head element and the given tail elements.

Assert

Asserts that all elements of a sequence meet a given condition otherwise throws an exception.

This method has 2 overloads.

AssertCount

Asserts that a source sequence contains a given count of elements.

This method has 2 overloads.

AtLeast

Determines whether or not the number of elements in the sequence is greater than or equal to the given integer.

AtMost

Determines whether or not the number of elements in the sequence is lesser than or equal to the given integer.

Backsert

Inserts the elements of a sequence into another sequence at a specified index from the tail of the sequence, where zero always represents the last position, one represents the second-last element, two represents the third-last element and so on.

Batch

Batches the source sequence into sized buckets.

This method has 4 overloads, 2 of which are experimental.

Cartesian

Returns the Cartesian product of two or more sequences by combining each element from the sequences and applying a user-defined projection to the set.

This method has 7 overloads.

Choose

Applies a function to each element of the source sequence and returns a new sequence of result elements for source elements where the function returns a couple (2-tuple) having a true as its first element and result as the second.

CompareCount

Compares two sequences and returns an integer that indicates whether the first sequence has fewer, the same or more elements than the second sequence.

Concat

Returns a sequence consisting of the head element and the given tail elements.

This extension was rendered obsolete in version 3.0 and eventually removed in version 4.0. Use Append from .NET instead that's been available since .NET Standard 1.6+, .NET Core 1.0+ and .NET Framework 4.7.1+.

Consume

Completely consumes the given sequence. This method uses immediate execution, and doesn't store any data during execution

CountBetween

Determines whether or not the number of elements in the sequence is between an inclusive range of minimum and maximum integers.

CountBy

Applies a key-generating function to each element of a sequence and returns a sequence of unique keys and their number of occurrences in the original sequence.

This method has 2 overloads.

CountDown

Provides a countdown counter for a given count of elements at the tail of the sequence where zero always represents the last element, one represents the second-last element, two represents the third-last element and so on.

DistinctBy

Returns all distinct elements of the given source, where "distinctness" is determined via a projection and the default equality comparer for the projected type.

This method has 2 overloads.

Duplicates

Returns all duplicate elements of the given source.

This method has 2 overloads.

EndsWith

Determines whether the end of the first sequence is equivalent to the second sequence.

This method has 2 overloads.

EquiZip

Returns a projection of tuples, where each tuple contains the N-th element from each of the argument sequences. An exception is thrown if the input sequences are of different lengths.

This method has 3 overloads.

Exactly

Determines whether or not the number of elements in the sequence is equals to the given integer.

ExceptBy

Returns the set of elements in the first sequence which aren't in the second sequence, according to a given key selector.

This method has 2 overloads.

Exclude

Excludes elements from a sequence starting at a given index

FallbackIfEmpty

Returns the elements of a sequence and falls back to another if the original sequence is empty.

This method has 6 overloads.

FillBackward

Returns a sequence with each null reference or value in the source replaced with the following non-null reference or value in that sequence.

This method has 3 overloads.

FillForward

Returns a sequence with each null reference or value in the source replaced with the previous non-null reference or value seen in that sequence.

This method has 3 overloads.

Flatten

Flattens a sequence containing arbitrarily-nested sequences.

This method has 3 overloads.

Fold

Returns the result of applying a function to a sequence with 1 to 16 elements.

This method has 16 overloads.

ForEach

Immediately executes the given action on each element in the source sequence.

This method has 2 overloads.

From

Returns a sequence containing the values resulting from invoking (in order) each function in the source sequence of functions.

This method has 4 overloads.

FullGroupJoin

Performs a Full Group Join between the and sequences.

This method has 4 overloads.

FullJoin

Performs a full outer join between two sequences.

This method has 4 overloads.

Generate

Returns a sequence of values consecutively generated by a generator function

GenerateByIndex

Returns a sequence of values based on indexes

GroupAdjacent

Groups the adjacent elements of a sequence according to a specified key selector function.

This method has 6 overloads.

Incremental

Incremental was redundant with Pairwise and so deprecated since version 2.1. It was eventually removed in version 3.0.

Index

Returns a sequence of where the key is the zero-based index of the value in the source sequence.

This method has 2 overloads.

IndexBy

Applies a key-generating function to each element of a sequence and returns a sequence that contains the elements of the original sequence as well its key and index inside the group of its key. An additional argument specifies a comparer to use for testing equivalence of keys.

This method has 2 overloads.

Insert

Inserts the elements of a sequence into another sequence at a specified index.

Interleave

Interleaves the elements of two or more sequences into a single sequence, skipping sequences as they are consumed.

Lag

Produces a projection of a sequence by evaluating pairs of elements separated by a negative offset.

This method has 2 overloads.

Lead

Produces a projection of a sequence by evaluating pairs of elements separated by a positive offset.

This method has 2 overloads.

LeftJoin

Performs a left outer join between two sequences.

This method has 4 overloads.

MaxBy

โš ๏ธ This method is obsolete. Use Maxima instead.

Returns the maxima (maximal elements) of the given sequence, based on the given projection.

This method has 2 overloads.

Maxima

Returns the maxima (maximal elements) of the given sequence, based on the given projection.

This method has 2 overloads.

MinBy

โš ๏ธ This method is obsolete. Use Minima instead.

Returns the minima (minimal elements) of the given sequence, based on the given projection.

This method has 2 overloads.

Minima

Returns the minima (minimal elements) of the given sequence, based on the given projection.

This method has 2 overloads.

Move

Returns a sequence with a range of elements in the source sequence moved to a new offset.

OrderBy

Sorts the elements of a sequence in a particular direction (ascending, descending) according to a key.

This method has 2 overloads.

OrderedMerge

Merges two ordered sequences into one. Where the elements equal in both sequences, the element from the first sequence is returned in the resulting sequence.

This method has 7 overloads.

Pad

Pads a sequence with default values if it is narrower (shorter in length) than a given width.

This method has 3 overloads.

PadStart

Pads a sequence with default values in the beginning if it is narrower (shorter in length) than a given width.

This method has 3 overloads.

Pairwise

Returns a sequence resulting from applying a function to each element in the source sequence and its predecessor, with the exception of the first element which is only returned as the predecessor of the second element

PartialSort

Combines OrderBy (where element is key) and Take in a single operation.

This method has 4 overloads.

PartialSortBy

Combines OrderBy and Take in a single operation.

This method has 4 overloads.

Partition

Partitions a sequence by a predicate, or a grouping by Boolean keys or up to 3 sets of keys.

This method has 10 overloads.

Permutations

Generates a sequence of lists that represent the permutations of the original sequence

Pipe

Executes the given action on each element in the source sequence and yields it

Prepend

Prepends a single value to a sequence

PreScan

Performs a pre-scan (exclusive prefix sum) on a sequence of elements

Random

Returns an infinite sequence of random integers using the standard .NET random number generator.

This method has 6 overloads.

RandomDouble

Returns an infinite sequence of random double values between 0.0 and 1.0.

This method has 2 overloads.

RandomSubset

Returns a sequence of a specified size of random elements from the original sequence.

This method has 2 overloads.

Rank

Ranks each item in the sequence in descending ordering using a default comparer.

This method has 2 overloads.

RankBy

Ranks each item in the sequence in descending ordering by a specified key using a default comparer.

This method has 2 overloads.

Repeat

Repeats the sequence indefinitely or a specific number of times.

This method has 2 overloads.

Return

Returns a single-element sequence containing the item provided.

RightJoin

Performs a right outer join between two sequences.

This method has 4 overloads.

RunLengthEncode

Run-length encodes a sequence by converting consecutive instances of the same element into a KeyValuePair<T, int> representing the item and its occurrence count.

This method has 2 overloads.

Scan

Peforms a scan (inclusive prefix sum) on a sequence of elements.

This method has 2 overloads.

ScanBy

Applies an accumulator function over sequence element keys, returning the keys along with intermediate accumulator states.

This method has 2 overloads.

ScanRight

Peforms a right-associative scan (inclusive prefix) on a sequence of elements. This operator is the right-associative version of the Scan operator.

This method has 2 overloads.

Segment

Divides a sequence into multiple sequences by using a segment detector based on the original sequence.

This method has 3 overloads.

Sequence

Generates a sequence of integral numbers within the (inclusive) specified range.

This method has 2 overloads.

Shuffle

Returns a sequence of elements in random order from the original sequence.

This method has 2 overloads.

SkipLast

Bypasses a specified number of elements at the end of the sequence.

SkipUntil

Skips items from the input sequence until the given predicate returns true when applied to the current source item; that item will be the last skipped

Slice

Extracts elements from a sequence at a particular zero-based starting index

SortedMerge

Merges two or more sequences that are in a common order (either ascending or descending) into a single sequence that preserves that order.

This method has 2 overloads.

Split

Splits the source sequence by a separator.

This method has 12 overloads.

StartsWith

Determines whether the beginning of the first sequence is equivalent to the second sequence.

This method has 2 overloads.

Subsets

Returns a sequence of representing all of the subsets of any size that are part of the original sequence.

This method has 2 overloads.

TagFirstLast

Returns a sequence resulting from applying a function to each element in the source sequence with additional parameters indicating whether the element is the first and/or last of the sequence

TakeEvery

Returns every N-th element of a source sequence

TakeLast

Returns a specified number of contiguous elements from the end of a sequence

TakeUntil

Returns items from the input sequence until the given predicate returns true when applied to the current source item; that item will be the last returned

ThenBy

Performs a subsequent ordering of elements in a sequence in a particular direction (ascending, descending) according to a key.

This method has 2 overloads.

ToArrayByIndex

Creates an array from an IEnumerable where a function is used to determine the index at which an element will be placed in the array.

This method has 6 overloads.

ToDataTable

Appends elements in the sequence as rows of a given object with a set of lambda expressions specifying which members (property or field) of each element in the sequence will supply the column values.

This method has 4 overloads.

ToDelimitedString

Creates a delimited string from a sequence of values. The delimiter used depends on the current culture of the executing thread.

This method has 15 overloads.

ToDictionary

Creates a dictionary from a sequence of key-value pair elements or tuples of 2.

This method has 4 overloads.

ToHashSet

Returns a hash-set of the source items using the default equality comparer for the type.

This method has 2 overloads.

ToLookup

Creates a lookup from a sequence of key-value pair elements or tuples of 2.

This method has 4 overloads.

Transpose

Transposes the rows of a sequence into columns.

TraverseBreadthFirst

Traverses a tree in a breadth-first fashion, starting at a root node and using a user-defined function to get the children at each node of the tree.

TraverseDepthFirst

Traverses a tree in a depth-first fashion, starting at a root node and using a user-defined function to get the children at each node of the tree.

Trace

Traces the elements of a source sequence for diagnostics.

This method has 3 overloads.

Unfold

Returns a sequence generated by applying a state to the generator function, and from its result, determines if the sequence should have a next element and its value, and the next state in the recursive call.

Window

Processes a sequence into a series of subsequences representing a windowed subset of the original

Windowed

Processes a sequence into a series of subsequences representing a windowed subset of the original

This method was removed and has been superseded by Window instead.

WindowLeft

Creates a left-aligned sliding window over the source sequence of a given size.

WindowRight

Creates a right-aligned sliding window over the source sequence of a given size.

ZipLongest

Returns a projection of tuples, where each tuple contains the N-th element from each of the argument sequences. The resulting sequence will always be as long as the longest of input sequences where the default value of each of the shorter sequence element types is used for padding.

This method has 3 overloads.

ZipShortest

Returns a projection of tuples, where each tuple contains the N-th element from each of the argument sequences. The resulting sequence is as short as the shortest input sequence.

This method has 3 overloads.

Experimental Operators

THESE METHODS ARE EXPERIMENTAL. THEY MAY BE UNSTABLE AND UNTESTED. THEY MAY BE REMOVED FROM A FUTURE MAJOR OR MINOR RELEASE AND POSSIBLY WITHOUT NOTICE. USE THEM AT YOUR OWN RISK. THE METHODS ARE PUBLISHED FOR FIELD EXPERIMENTATION TO SOLICIT FEEDBACK ON THEIR UTILITY AND DESIGN/IMPLEMENTATION DEFECTS.

Use of experimental methods requires importing the MoreLinq.Experimental namespace.

Aggregate

Applies multiple accumulator queries sequentially in a single pass over a sequence.

This method has 8 overloads.

Await

Creates a sequence query that streams the result of each task in the source sequence as it completes asynchronously.

This method has 2 overloads.

AwaitCompletion

Awaits completion of all asynchronous evaluations irrespective of whether they succeed or fail. An additional argument specifies a function that projects the final result given the source item and completed task.

Memoize

Creates a sequence that lazily caches the source as it is iterated for the first time, reusing the cache thereafter for future re-iterations. If the source is already cached or buffered then it is returned verbatim.

Merge

Concurrently merges all the elements of multiple asynchronous streams into a single asynchronous stream. An overload with an additional parameter specifies the maximum concurrent operations that may be in flight at any give time.

This method has 2 overloads.

TrySingle

Returns the only element of a sequence that has just one element. If the sequence has zero or multiple elements, then returns a user-defined value that indicates the cardinality of the result sequence.

This method has 2 overloads.

morelinq's People

Contributors

ambientlion avatar anders9ustafsson avatar angularsen avatar arithmomaniac avatar atifaziz avatar balazsbotond avatar c9952594 avatar cammerman avatar clement-jean avatar erikschierboom avatar fsateler avatar georgevovos avatar githubpang avatar i3arnon avatar jnyrup avatar johannesrudolph avatar jskeet avatar julianlettner avatar klmr avatar kvam avatar leandromoh avatar miffyliye avatar orace avatar quassnoi avatar sholland1 avatar sid-6581 avatar tagc avatar viceroypenguin avatar vladimirrybalko avatar yln avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

morelinq's Issues

Scan operation

Originally reported on Google Code with ID 9

A primitive that implements the [scan/prefix sum][1] operation. Useful in
many scenarios, e.g. radix sort can be implemented efficiently using such
an operation.

Scans also form an integral part of the Haskell Prelude and stream
programming APIs (see CUDPP for NVIDIA CUDA) โ€“ in part because it can be
implemented work efficiently for parallel architectures.

[1]: http://en.wikipedia.org/wiki/Prefix_sum

Reported by konrad.rudolph on 2009-02-17 20:07:33


- _Attachment: [scan.patch](https://storage.googleapis.com/google-code-attachments/morelinq/issue-9/comment-0/scan.patch)_

EvenMoreLINQ branch (r119) build is broken

Originally reported on Google Code with ID 37

What steps will reproduce the problem?

1. Check out the branch EvenMoreLINQ:
   https://morelinq.googlecode.com/svn/branches/EvenMoreLINQ
2. Run build.cmd or buildw.cmd in the root of the working copy.

What is the expected output? What do you see instead?

Expected the build to succeed across the entire solution. Instead the test 
project fails with the following extract (see attached file for full 
output) towards the end that highlights the problem:

"C:\EvenMoreLINQ\MoreLinq.sln" (default target) (1) ->
"C:\EvenMoreLINQ\MoreLinq.Test\MoreLinq.Test.csproj" (default target) (3) -
>
(CoreCompile target) ->
  CSC : error CS2001: Source file 'Combinatorics.cs' could not be found

    0 Warning(s)
    1 Error(s)


Reported by azizatif on 2010-01-17 11:21:08

  • Blocking: #34

- _Attachment: [build.txt](https://storage.googleapis.com/google-code-attachments/morelinq/issue-37/comment-0/build.txt)_

Review: MoreEnumerable.Slice()

Purpose of code changes on this branch:

Rev 140: Implementation of the Slice operator which allows extraction of the middle elements of a sequence, given a start index and a count. Slice is functionally equivalent to: sequence.Skip(startIndex).Take(count) - however it is clearer, and contains an optimization for collections that implement IList<T>.

When reviewing my code changes, please focus on:

  • The public interface of the extension method.
  • The effectiveness and clarity of the available XML comment documentation.
  • How well this operator fits into the MoreLINQ ecosystem of extension methods.
  • The extent of coverage available from the corresponding unit tests.
  • Whether edge cases are correctly identified and handled in the implementation and tests.

After the review, I'll merge this branch into:

/trunk

Reported by @AmbientLion on 2010-01-23 18:47:09

Originally reported on Google Code with ID 49

Review: MoreEnumerable.Incremental()

Originally reported on Google Code with ID 46

Purpose of code changes on this branch:

Rev 137: Implementation of the Incremental operator which visits each
adjacent pair of elements in a sequence: {N,N+1}, {N+1,N+2}, {N+2,N+3} ...
and applies a projection to them. An overload is available that is also
supplied the zero-based index of the *second* element in the pair. The
number of items in the result sequence will always be one less than in the
source. Incremental returns an empty sequence if passed a sequence of less
than two items. Incremental operates in a deferred, streaming fashion. 

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-23 17:16:35

Add Exhaust/Consume operator

Originally reported on Google Code with ID 11

An Exhaust operator exists in the test project. It should be offered as a 
public operator in the base library.

Rationale: There is already ForEach and Exhaust is just the loop factored 
out, permitting consumption of a source without side-effect where needed. 
Together with Pipe, ForEach can be implemented in terms of Pipe plus 
Exhaust.

Also, while we're at it, consider Consume versus Exhaust. ;)

Reported by azizatif on 2009-02-17 23:42:21

DistinctBy should allow a null comparer

Originally reported on Google Code with ID 3

What steps will reproduce the problem?

int[] source = { 1, 2, 3, 2, 1 };
source.DistinctBy(x => x, null);

What is the expected output? What do you see instead?

The expected output is { 1, 2, 3 } assuming the default comparer 
implementation since a null comparer is supplied. This would be consistent 
with the Enumerable.Distinct operator from Microsoft's base LINQ-to-
Objects implementation. However, what one sees instead is a 
ArgumentNullException from DistinctBy.

Reported by azizatif on 2009-02-15 18:58:27

Add "Dump" methods

We should have "Dump" methods (and possibly equivalents which don't consume, just like ForEach vs Pipeline or whatever they'll be called) to make it easier to dump a sequence to the console, another TextWriter, or some arbitrary Action<string> consumer.


Originally reported on Google Code with ID 22

Reported by @jskeet on 2009-03-25 20:34:19

New methods MinOrDefault and MaxOrDefault

When you start playing with LINQ queries over sequences of elements (e.g. getting min / max value for enumerable source) sooner or later you will come across this one -- the InvalidOperationException (โ€œSequence contains no elementsโ€).

The problem occurs as by default queries like IEnumerable<T>.Min(โ€ฆ) and IEnumerable<T>.Max(โ€ฆ) do not play nicely if you try to execute them on an empty sequence and just throw the exception described above. Unfortunately these methods do not have a corresponding counterpart like Single(โ€ฆ) /SingleOrDefault(โ€ฆ) that is smart enough to query the sequence if it is not empty or alternatively use the default value without raising an exception.

Basically you got two options now:

  • Either perform the check on the enumerable sequence every time you are querying it
  • OR integrate the logic in an extension method.

The second approach is much preferable so letโ€™s add the missing link.

http://blogs.telerik.com/manoldonev/posts/08-10-17/linq_sequence_contains_no_elements_extension_methods_to_the_rescue.aspx


Originally reported on Google Code with ID 28

Reported by anton.georgiev on 2009-09-17 08:56:23

Consider adding Zip operator

Originally reported on Google Code with ID 2

Consider adding Zip operator for sequences, somewhat akin to the built-in 
zip function in Python. See:
http://www.python.org/doc/2.5.2/lib/built-in-funcs.html#l2h-81

Zip has the following logical behavior given two sequences:

zip((1, 2, 3), (4, 5, 6)) -> ((1, 4), (2, 5), (3, 6))

It returns tuples, where each tuple contains the N-th element from each of 
the argument sequences. The returned sequence is truncated in length to 
the length of the shortest argument sequence.

The attached patch contains a proposed implementation along with unit 
tests. I think Zip belongs in the grouping category of operators (since it 
groups elements by their position).

It looks like Zip will make it into .NET Framework 4.0 (see 
http://codebetter.com/blogs/matthew.podwysocki/archive/2008/11/16/functiona
l-net-4-0-tuples-and-zip.aspx) so all the better to make it available to 
3.5 applications via this project.

Reported by azizatif on 2009-02-13 00:01:12


- _Attachment: [Zip.patch](https://storage.googleapis.com/google-code-attachments/morelinq/issue-2/comment-0/Zip.patch)_

Code review request for reorg

Originally reported on Google Code with ID 23

Purpose of code changes on this branch:

Re-organize MoreLINQ so that all operators are implemented under the
Enumerable class, providing several advantages over the current structure
that classifies operators under their so-called category class.

When reviewing my code changes, please focus on:

The branch puts all operators under a single class called Enumerable, much
like the base LINQ operators it extends. However, each operator resides in
its own file and uses a partial modifier to allow the Enumerable definition
to fan out. The benefits of this new structure over the current are the
following:

* Regions are not needed to superficially organize and delimit operators
within a class just because the class seems to be growing big as new
overloads and operators are added to it. Regions work fine as a visual
navigation aid if you are in a sophisticated IDE like VS, but not when you
are browsing the source through other means, such as the online Subversion
browser, terminal or e-mail.

* Categorization of the operator is more of a documentation and learning
aid than an implementation concern. Once the MoreLinq.Pull namespace is
imported, all types extending IEnumerable<T> are available irrespective of
how the authors categorized them. The point is, it doesn't serve as aid for
the user of the pull operators. In the new organization, categorization
could be done (if absolutely needed) with a custom XML doc summary element.

* A single partial Enumerable is simple than multiple category classes.
There is no added benefit of the latter. Naming LINQ operators is hard
enough. Proper categorization adds additional subjectivity and headache for
authors. Before you can add an operator, you need to think about how to
name it and categorize (the exercise may not be entirely unhealthy or
useless). With the new organization, you just put it under Enumerable.

* If an operator needs to be located, one has to first try and remember the
class category, open that file and then add the operator or overload an
existing at the right place. With the new organization, you just create a
new file, define Enumerable as partial and add the operator implementation.
For an existing operator, locating its source code is dead easy because the
file is named after the operator.

* Since each operator lies in it own file in the proposed new organization,
there is less contention or risk of edit conflicts between authors working
on the same source file.

* With the proposed new organization, providing on-line links to a single
operator and all its overloads is as simple as providing a URL the
operator's file, as in http://tinyurl.com/MoreLinq-DistinctBy, whereas with
the current organization, the best you can do is point someone to the
category class and then ask them to look for the operator under there.

The are, however, two downsides, none of which seem to outweigh the
aforementioned advantages:

* All 134 tests now appear under a single fat fixture. For now, I have
classified the operators by category using the Category attribute from
NUnit. With this, you can still decide to run tests of only a single
category (using, for example, the /include switch from nunit-console) or
visually distinguish them in the GUI.

* If someone wants to use an operator that is not implemented as an
extension method or invoke it without the extension invocation syntax, then
the compiler may be confused between System.Linq.Enumerable and
MoreLinq.Pull.Enumerable. The conflict occurs only if System.Linq and
MoreLinq.Pull are imported in the same source file. This could be resolved
in one of two ways: (i) we use MoreEnumerable instead of Enumerable or (ii)
let the user of the code decide by introducing type aliases to her liking,
as in:

using LinqEnumerable = System.Linq.Enumerable;
using MoreEnumerable = MoreLinq.Pull.Enumerable;

After the review, I'll merge this branch into:
/trunk

Reported by azizatif on 2009-04-04 22:27:03

Review: MoreEnumerable.Repeat()

Originally reported on Google Code with ID 35

Purpose of code changes on this branch:

Rev 118: Implementation of the Repeat() extension method that operates on
sequences rather than single elements. This extension method serves as a
logical expansion of the Enumerable.Repeat() method - except it repeats all
of the elements of a sequence, rather than a single element. It is a
building block for more sophisticated operators such as NestedLoops() and
Permutations().

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-17 05:54:12

Review: MoreEnumerable.PermutedSubsets()

Originally reported on Google Code with ID 38

Purpose of code changes on this branch:

Rev 122: Implementation of the PermutedSubsets() extension method which
efficiently generates the set of all permutations of the set of all subsets
of a sequence. An overload is provided that restricts the results to only
subsets of a given size. The implementation is built by iteratively
composing the Subsets() and Permutations() operators.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.

After the review, I'll merge this branch into:
/trunk


Reported by ambientlion on 2010-01-17 17:09:05

Make the assembly strong named

Originally reported on Google Code with ID 30

Without a strong name the assembly cannot be referenced by other strong 
named assemblies.

I know I can just grab the code and sign it myself, but it would be better 
if you could save me the hassle...

Reported by martinho.fernandes on 2009-11-01 09:56:10

Make the assembly strong named

Originally reported on Google Code with ID 31

Without a strong name the assembly cannot be referenced by other strong 
named assemblies.

I know I can just grab the code and sign it myself, but it would be better 
if you could save me the hassle...

Reported by martinho.fernandes on 2009-11-01 09:56:50

Consider renaming Zip methods

(No need for one issue per method.)

We should look at what .NET 4.0 is going to do in terms of Zip methods, and try to match those so it's a simple hand-over when moving from 3.5 + MoreLinq to 4. We should also make sure that the duplicate naming doesn't cause a problem - or have a separate build which doesn't include it.

When .NET 4.0 beta 1 comes out we can take a look.


Originally reported on Google Code with ID 25

Reported by @jskeet on 2009-04-07 09:53:44

Silverlight Trace methods could output using Console.WriteLine or Debug.WriteLine

Silverlight doesn't currently support the concept of tracing, which leaves the Trace methods a little lacking, as you know. Perhaps Trace could in the Silverlight implementation could use Console.WriteLine or Debug.WriteLine or both so that we have some pseudo-tracing.


Originally reported on Google Code with ID 19

Reported by jeffmagic on 2009-03-12 13:32:45

Error in description of TakeEvery

Originally reported on Google Code with ID 27

http://code.google.com/p/morelinq/source/browse/trunk/MoreLinq/TakeEvery.cs

The example documentation says "numbers.Every(2);" which obviously should
be "numbers.TakeEvery(2);"

Reported by Kramieb on 2009-09-11 06:44:52

IList<T> view operators from Stephen Cleary

Merge some or all of the operators from @StephenCleary

Operators for IEnumerable<T> lifted from List<T>/Array:

int IndexOf<T>(this IEnumerable<T> source, T value)
int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate) // List<T>.FindIndex
int LastIndexOf<T>(this IEnumerable<T> source, T value)
int LastIndexOf<T>(this IEnumerable<T> source, Func<T, bool>  predicate) // List<T>.FindLastIndex

Operators for IList<T> lifted from List<T>/Array:

IList<T> AsReadOnly<T>(this IList<T> list)
void CopyTo<T>(this IList<T> list, int index, IList<T> destination, int destinationIndex, int count)
void CopyTo<T>(this IList<T> list, IList<T> destination, int destinationIndex)
void CopyTo<T>(this IList<T> list, IList<T> destination)
int LastIndexOf<T>(this IList<T> list, T value)
int LastIndexOf<T>(this IList<T> list, Func<T, bool> predicate) // List<T>.FindLastIndex

Operators optimized for IList from Enumerable (.NET 3.5):

IList<TResult> Select<TSource, TResult>(this IList<TSource> list, Func<TSource, TResult> selector)
IList<TResult> Select<TSource, TResult>(this IList<TSource> list, Func<TSource, int, TResult> selector)
IList<T> Skip<T>(this IList<T> list, int offset)
IList<T> Take<T>(this IList<T> list, int count)
IList<T> Reverse<T>(this IList<T> list)
T Last(this IList<T> list, Func<T, bool> selector)
T LastOrDefault(this IList<T> list, Func<T, bool> selector)

Operators optimized for IList<T> from EnumerableEx (Rx):

IList<T> Repeat<T>(this IList<T> list, int count)
IList<TResult> Zip<TFirst, TSecond, TResult>(this IList<TFirst> first, IList<TSecond> second, Func<TFirst, TSecond, TResult> zipper)
IList<T> Memoize<T>(this IList<T> list)
IList<T> MemoizeAll<T>(this IList<T> list)

Sources optimized for IList<T> from EnumerableEx (Rx):

IList<T> Return<T>(T source)
IList<T> Repeat<T>(T source, int count)
IList<T> Concat<T>(params IList<T>[] others)
IList<T> Concat<T>(IList<IList<T>> lists)
IList<T> Generate<T>(int count, Func<T> generator)
IList<T> Generate<T>(int count, Func<int, T> generator)

My own sequence/list operators

Zip (3-argument version):

IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, IEnumerable<TThird> third, Func<TFirst, TSecond, TThird, TResult> zipper)
IList<TResult> Zip<TFirst, TSecond, TThird, TResult>(this IList<TFirst> first, IList<TSecond> second, IList<TThird> third, Func<TFirst, TSecond, TThird, TResult> zipper)

Flatten:

```c#
IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> list)
IList<T> FlattenList<T>(this IList<IList<T>> list)

Select (bidirectional projection):

IList<TResult> Select<TSource, TResult>(this IList<TSource> list, Func<TSource, TResult> selector, Func<TResult, TSource> reverseSelector)

Slice:

IList<T> Slice<T>(this IList<T> list, int offset, int count)
IList<T> Step<T>(this IList<T> list, int step)

CopyBackward:

void CopyBackward<T>(this IList<T> list, int index, IList<T> destination, int destinationIndex, int count)

Originally reported on Google Code with ID 32

Reported by stephenandmandy on 2009-11-20 15:29:25

Review: MoreEnumerable.Subsets()

Originally reported on Google Code with ID 34

Purpose of code changes on this branch:

Rev 117 - Implementation of a set of operators that produce a sequence of
subsets of an original source sequence. Subsets are produced in a deferred,
streaming manner. There are two primary overloads - one that produces all
subsets of a given sequence (of which there are 2^N), and an overload that
produces all k-sized subsets of a sequence (of which there are N!/((N-m)!m!)).

When reviewing my code changes, please focus on:

* The public interface of the extension methods.
* The effectiveness and clarity of the available XML comment documentation.
* How well these operators fit will into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* The clarity and division of responsibility of the implementation.
* Whether edge cases are correctly identified and handled in the
implementation and tests.

After the review, I'll merge this branch into:
/trunk


Reported by ambientlion on 2010-01-17 05:25:58

Rename Pipe to ViaAction/Cause/Visit

The Pipe operator sounds too general and vague. Any set of LINQ operations chained together could be seen as a pipeline or pipe formation/composition. Pipe also does not imply any side effect. Consequently, consider renaming Pipe to ViaAction. ViaAction clearly states two things: (1) the operator is pass-through, as in via, and (2) it implies an action, which for the majority case is understood to be a side-effect.


Originally reported on Google Code with ID 10

Reported by @atifaziz on 2009-02-17 21:05:47

Review: MoreEnumerable.Segment()

Originally reported on Google Code with ID 45

Purpose of code changes on this branch:

Rev 136: Implementation of the Segment operator which transforms a sequence
int a series of sequence that divide up the elements of the original
sequence. Segment uses a caller-supplied segmentation detector which
informs Segment when an element should begin a new segment. Overloads exist
which supply the segmentation detector with an element, or an element and
its zero-based index, or an element, previous element and index.
Individuals segments are buffered, but the overall operation is performed
in a streaming fashion - segments never visited are not computed.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.


After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-23 17:13:03

Review: MoreEnumerable.PairUp()

Originally reported on Google Code with ID 42

Purpose of code changes on this branch:

Rev 127: Implementation of the PairUp extension method, which combines
adjacent pairs in the source sequence and returns the result of applying a
user-defined projection to them. PairUp can operate on either odd-length or
even-length sequences. In the case of add-length sequences, an optional
imbalance strategy can be supplied, which defines whether PairUp should
skip the last (unpaired) value, or process the terminal element with a
default value pairing. The result of PairUp applied to a non-empty
sequence, will always be a sequence of half the length of the source sequence.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-18 05:08:29

Trace methods should only work on TRACE define

As with other Trace methods, the MoreLINQ Trace methods should not operate if the TRACE define is not specified.


Originally reported on Google Code with ID 18

Reported by jeffmagic on 2009-03-11 04:34:30

Need a wiki page for each operator

We should really create a wiki page with a simple example of each operator as we implement it.


Originally reported on Google Code with ID 4

Reported by @jskeet on 2009-02-15 21:28:49

AssertCount still asserts in a release

Originally reported on Google Code with ID 16

Currently, the AssertCount call does not actually act like a traditional 
assert as it is not ignored in a release build. Maybe it should have the 
ConditionalAttribute applied or be renamed to reflect this non-traditional 
behaviour.

Reported by jeffmagic on 2009-03-10 22:15:25

Review: MoreEnumerable.OrderBy() and MoreEnumerable.ThenBy()

Originally reported on Google Code with ID 48

Purpose of code changes on this branch:

Rev 139: Implementation of the OrderBy and ThenBy operators which can be
supplied a parameter to control the direction of sorting. This allows
callers to avoid complicating their code with branching logic to call
OrderByDescending/ThenBeDescending when the sort direction is only known at
run-time.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.
* Whether operators of the same name as those in LINQ may have negative
consequences.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-23 18:33:24

TakeRangeEvery method

TakeEvery is great for taking just one item at regular intervals, but it would also be useful to take a range of items at regular intervals.

TakeRangeEvery(this IEnumerable<T> items, int rangeCount, int step)

Originally reported on Google Code with ID 17

Reported by jeffmagic on 2009-03-11 04:22:30

Replace ImbalancedZipStrategy with distinct Zip* methods

The current use of an enumeration (ImbalancedZipStartegy) to express the required behavior seems awkward because it's not something you want to be able to vary externally, which is usually why you would make a parameter or argument. Plus, it's a little cumbersome to write and read back in code and not very LINQ-ish in spirit. The enumeration could certainly be used internally for sharing the implementation logic but the public API should use distinct and clear operator names that imply the strategy. For example:

  • EquiZip: Sequences must be equal in length otherwise throw error
  • Zip: Truncates to shorter of the two sequences
  • ZipLongest: Uses longer of the two sequences while padding shorter of the two

There is a very subtle yet major idea behind extension methods and LINQ that the enumeration also works against. If the enumerable source type wants to provide an optimization for an operator, it can do so by providing a method by the same name and signature as the operator in question. If we use an enumeration that comes from MoreLINQ then the other type has to take in a dependency that won't be looked upon lightly. If we take the approach of embodying the strategy in the name (assuming this is a compile-time decision), then we have simple signatures with Zip, EquiZip and ZipLongest being distinct and clear names. Now, if there is a type called SuperDuperList<T> that wants to provide an optimization for Zip, EquiZip and ZipLongest (or any one of the three) then one can do so using simply base and generic types. Right now, with the enumeration, there is no choice but to support all strategies and take a hit on MoreLINQ! This is how Enumerable.Contains works. When using Contains on variables typed as List<T> or IList<T>, the LINQ extension method is not used! If one wants to force use of the LINQ's Contains implementation then one has to hop over AsEnumerable first.

This approach keeps MoreLINQ close to how LINQ operators should be designed, taking built-in ones as guidance.

P.S. This issue was creation out of comments in issue #6.


Originally reported on Google Code with ID 24

Reported by @atifaziz on 2009-04-07 07:35:26

Silverlight 2.0 assembly

Originally reported on Google Code with ID 13

It would be great if the source was compilable for Silverlight deployment 
as well as regular .NET framework use. This should, in most cases, be as 
simple as using the same source and compiling for Silverlight.

Reported by jeffmagic on 2009-02-18 17:46:18

Add BreakWhen method

Originally reported on Google Code with ID 15

There are some nice Assert methods to simplify assertion but it would also 
be nice to specify breakpoints in a similar manner for use when debugging 
problems. It would certainly be easier than adding conditional breakpoints.

Reported by jeffmagic on 2009-03-10 22:11:10

Review: MoreEnumerable.Random()

Originally reported on Google Code with ID 33

Purpose of code changes on this branch:

Implementation of a set of operators that allow generating sequences of
random numbers. Overloads are available that map to the Next() and
NextDouble() methods of System.Random. All overloads of Random() are
intended to be lazy, streaming generators that produce an infinite sequence
of random numbers (compliant with the constraints placed by the particular
overload used). 

When reviewing my code changes, please focus on:

* The public interface of the extension methods.
* Their compatibility with typical use and public interface of the
System.Random class.
* The effectiveness and clarity of the available XML comment documentation.
* How well these operators fit will into the MoreLINQ ecosystem of
extension methods.
* The correctness of the implementation and the extent of coverage
available from the corresponding unit tests.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-17 03:56:27

Review: MoreEnumerable.RunLengthEncode()

Originally reported on Google Code with ID 40

Purpose of code changes on this branch:

Rev 125: Implementation of the RunLengthEncode() extension method which
operates on sequences and produces a new sequence representing the
occurrence of repeated runs of the same value in the original. The
resulting (transformed) sequence consists of zero or more
KeyValuePair<T,int> elements - where the Key identifies the item and the
Value is the occurrence count of that item in the original sequence.
RunLengthEncode has an overload that allows the caller to supply equality
semantics for the elements of the sequence being transformed.
RunLengthEncode is intended to operate in a deferred, streaming fashion -
allowing it to process sequences of arbitrary (or infinite) length.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.
* Whether the operator adheres to the description and behavior described above.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-18 03:14:07

Add a roadmap

It would be helpful to add a wiki page that outlines a roadmap for the this project. The roadmap could be expanded later on as the vision and scope develops, but it should start by giving a clear idea of what constitutes version 1.0. For example, how many operators are enough for 1.0? Is that any measure? And so on.


Originally reported on Google Code with ID 7

Reported by @atifaziz on 2009-02-16 23:03:17

SelectWithIndex (or something similar)

Originally reported on Google Code with ID 29

I've seen a number of questions like this one: 
http://stackoverflow.com/questions/1593235/linq-to-xml-dictionary-conversion

Where the overload for Select taking a `Func<TSource,int,TResult>` is 
basically used to create key/value pairs. We should make this easier with a 
single method call - either using KeyValuePair or a new IndexValuePair 
struct.

Reported by jonathan.skeet on 2009-10-20 08:52:33

Review: MoreEnumerable.SortedMerge

Originally reported on Google Code with ID 41

Purpose of code changes on this branch:

Rev 126: Implementation of SortedMerge operator which combines two or more
ordered sequences into a single sequence that preserves the order. Merge
allows callers to supply comparison semantics using an overload that
accepts an IComparer<T>. SortedMerge operates in a deferred and streaming
fashion - it uses a (relatively) efficient algorithm whose run time is
proportional to the combined length of all sequences being merges.

SortedMerge DOES NOT guarantee a stable ordering if elements in multiple
sequences have the same value - meaning that no promises are made about
which items will appear first in the merged sequence. The results of
performing a SortedMerge on sequences that are not ordered or are not in
the same order is undefined.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.
* Whether the computational complexity (big-O) of the algorithm used is
appropriate for the problem being solved.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-18 04:27:31

Code review request for Split

Originally reported on Google Code with ID 8

Purpose of code changes on this branch:

When I added the Batch operator, I thought I could implement it in terms 
of a generalized Split operator. I was wrong, but the damage was already 
done and I had implemented and factored out all the work to implement a 
Split operator for any enumerable source. However, I have doubts about its 
general usefulness and is the reason why I am putting it in a branch.

When reviewing my code changes, please focus on:

I would appreciate it if you could review and comment on "utility" and 
general application of this operator. If you find that it makes good sense 
then I can merge it back into the turnk. Otherwise the branch can just 
serve as an archive.

After the review, I'll merge this branch into:
/trunk


Reported by azizatif on 2009-02-17 18:17:57

Implement Concat in terms of existing LINQ operations

Originally reported on Google Code with ID 1

This is only a suggestion to simplify the implementation of 
Concatenation.Concat operator in MoreLINQ. The attached patch proposes to 
implement Concat in terms of existing LINQ operators, yielding shorter 
code and reusing a tested base. Hopefully, you agree.

Reported by azizatif on 2009-02-12 22:42:40


- _Attachment: [Concatenation.patch](https://storage.googleapis.com/google-code-attachments/morelinq/issue-1/comment-0/Concatenation.patch)_

Review: MoreEnumerable.Partition()

Originally reported on Google Code with ID 44

Purpose of code changes on this branch:

Rev 128: Implementation of the Partition extension method, which transforms
a sequence into a series of sequences whose elements are defined by a set
of supplied partition sizes. Partition can be passed a projection function,
in which case the result is a sequence formed by first partitioning and
then transforming each partition into a result. An underflow strategy can
also be supplied, which control how partition behaves when there are
elements remaining in the source sequence after all explicit partitions
have been evaluated. Partition uses an unusual strategy for coping with
returning the "rest" of a sequence - it uses a special IEnumerable
implementation which caches the original enumerator.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.
* Whether the YieldRestEnumerator implementation is correctly implemented
and appropriately tested.
* Whether there is an easier way to deal with yielding the remainder of a
sequence, other than the YieldRestEnumerator approach.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-18 17:38:40

Review: MoreEnumerable.While()

Originally reported on Google Code with ID 47

Purpose of code changes on this branch:

Rev 138: Implementation of the While operator which consumes a sequence and
returns a projection of each element while some condition is true. Unlike
TakeWhile(), While supplies the condition delegate with the current and
previous element in the sequence, allowing conditions to be based on
changes between elements of the sequence. Wile operators in a deferred and
streaming manner.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.


After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-23 18:18:20

Add support for enumerable noise sets

A useful method to perform algorithms that use noise would be to set up the noise data as an enumeration, much like Enumerable.Range(int start, int count). The proposed method would be Enumerable.Noise(int seed), yielding infinite procedural noise generation.

Then, to take five random numbers one would call var randomNumbers = Enumerable.Noise(seed).Take(5);

There is alot of uses for floating point noise aswell, mainly in procedural fractal generation.

Enumerable.Noise<float>(seed); // Generate noise between 0-1
Enumerable.NoiseSigned<float>(seed); // Generate noise between (-1)-1

Due to the problem of infinite enumeration, foreach loops on raw enumerations of noise would be problematic. Perhaps one should set up a maximum range of numbers?


Originally reported on Google Code with ID 21

Reported by l.jarvensivu on 2009-03-25 14:40:32

New method: Sequence.Traverse

Sequence.Generate is able to traverse linked lists of reference types, but it produces an infinite list and also doesn't check for null (nor should/could it, generally speaking).

So it has to be used in a boilerplate idiom where it is combined with TakeWhile, e.g.

Exception innermost = Sequence.Generate(caught, e => e.InnerException).While(e => e != null).Last();

The name Generate then becomes a little misleading, as we are not generating a new list but traversing an existing list.

Also it is a bit counter-intuitive to have the check for null termination appearing after the Generate call - perfectly safe due to the laziness, but it looks dodgy.

Given the usefulness of this pattern, and the fact that we are not really generating anything, it might make sense to make it a separate method called Traverse, limited of course to reference types:

public static IEnumerable<TResult> Traverse<TResult>(TResult initial,
    Func<TResult, TResult> generator) where TResult : class
{
    for (TResult current = initial; current != null; current = generator(current))
        yield return current;
}

Originally reported on Google Code with ID 14

Reported by daniel.earwicker on 2009-03-10 11:18:24

ToDelimitedString delimits incorrectly on sequence starting with empty strings

What steps will reproduce the problem?

Call MoreEnumerable.ToDelimitedString on a sequence where the initial values of the sequence result in an empty strings.

What is the expected output? What do you see instead?

Expect all values of the sequence to be delimited. Instead values are delimited only after the first value in the sequence that results in a non-empty string.

The following IronPython code illustrates the problem:

IronPython 2.6 (2.6.10920.0) on .NET 2.0.50727.3603
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr
>>> clr.AddReference('MoreLinq')
>>> from MoreLinq.MoreEnumerable import ToDelimitedString
>>> print ToDelimitedString(['foo','bar','baz'])
foo,bar,baz
>>> print ToDelimitedString(['foo','','baz'])
foo,,baz
>>> print ToDelimitedString(['','','baz'])
baz
>>>

The last statement, should have resulted in:

,,baz

Originally reported on Google Code with ID 43

Reported by @atifaziz on 2010-01-18 16:17:53

Review: MoreEnumerable.RandomSubset()

Originally reported on Google Code with ID 39

Purpose of code changes on this branch:

Rev 123: Implementation of the RandomSubset extension method which returns
a sequence of randomly selected elements from the original sequence. This
operator is deferred but it is NOT streaming. This operator performs a
random shuffle of the original elements, from which it then selects the
first N elements. As an optimization, only a partial shuffle is performed -
instead of a complete shuffle.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.
* The potential performance implications of the selected algorithm.

After the review, I'll merge this branch into:
/trunk


Reported by ambientlion on 2010-01-17 17:31:58

Adding series generation/comprehension methods

Originally reported on Google Code with ID 5

Consider adding series generation/comprehension methods for programmatic
generation of collections "from scratch".

Not sure this would not technically be called a LINQ operator, but it is
very useful for generating data permutations more complex than a 1-step
range (as with Enumerable.Range), for tests or otherwise, as well as
generating ordinals to be paired with collection items using the Zip operator.

The method would have the following behavior given fairly vanilla generator
and terminal functions:

Series.Expand(2, n => n * n, n > 1000) => (2, 4, 8, 16, 32, 64, 128, 256, 512)

The method would have the following behavior given a vanilla generator
function and an element count:

Series.Expand(1, n => n + 3, 8) => (1, 4, 7, 10, 13, 16, 19, 22)

The method would generate new elements lazily and stream them.  This would
also allow an effectively "infinite" sequence to be generated, for example
for the purposes of Zipping with a collection of indeterminate length.

I have attached a patch with a proposed implementation and tests.  I placed
the method in its own file and static class because it is not strictly an
operator like the others.

Reported by CAmmerman on 2009-02-16 02:55:14


- _Attachment: [Series.patch](https://storage.googleapis.com/google-code-attachments/morelinq/issue-5/comment-0/Series.patch)_

Allow caller to specify value for padding shorter of Zip sequences

I think it would be good to allow the caller to control what is being used to pad the shorter collection if desired, rather than relying on default(TResult). Especially for numerics, where 0 may very well have a meaning for the caller, other than "not there".

Since this would change the method signature, new method overrides would probably be required. These methods would probably have no need for a zip strategy argument either.

Here is the method signature I would envision:

private static IEnumerable<TResult> ZipImpl<TFirst, TSecond, TResult>(
    IEnumerable<TFirst> first, 
    IEnumerable<TSecond> second, 
    Func<TFirst, TSecond, TResult> resultSelector,
    TFirst padFirst,
    TSecond padSecond)

Originally reported on Google Code with ID 6

Reported by @cammerman on 2009-02-16 03:05:10

Review: MoreEnumerable.NestedLoops()

Originally reported on Google Code with ID 36

Purpose of code changes on this branch:

Rev 119 - Implementation of the NestedLoops() operator, which expands an
Action into a sequence whose length is equivalent to the total number of
iterations of a set of nested loop. NestedLoops() builds on the Repeat()
operator to allow the dynamic construction of nested loops. It is passed an
Action and an IEnumerable<int> that reflects the number of iterations of
each level of the nested loop. The result is a sequence which repeats the
Action parameter as many times as the product of the loop counts. This
method allows the construction of virtualized, streaming sequences whose
length exceeds the representational bounds of Int32, Int64 and even
decimal. This is useful in those cases where you want to overcome the range
limitations of the built-in .NET numeric types (the Permutations extension
method is the primary beneficiary and best example of this).

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.
* Whether this is the simplest way to support the requirements of operators
like Permutations() - or whether it's overkill.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-17 06:30:59

Review: MoreEnumerable.Exclude()

Originally reported on Google Code with ID 50

Purpose of code changes on this branch:

Rev 144: Implementation of the Exclude operator which eliminates a range of
items from a sequence. Exclude is the logical inverse of Slice and can
exclude elements from any portion of a sequence. Exclude operates in a
deferred and streaming manner.

When reviewing my code changes, please focus on:

* The public interface of the extension method.
* The effectiveness and clarity of the available XML comment documentation.
* How well this operator fits into the MoreLINQ ecosystem of
extension methods.
* The extent of coverage available from the corresponding unit tests.
* Whether edge cases are correctly identified and handled in the
implementation and tests.

After the review, I'll merge this branch into:
/trunk

Reported by ambientlion on 2010-01-24 00:31:58

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.