GitXplorerGitXplorer
D

Py-Seq

public
0 stars
0 forks
0 issues

Commits

List of commits on branch master.
Unverified
a6ec84d3c42ad6aa6c7cdae25578a82b845f903a

Add documentation

DDegubi committed 4 years ago
Unverified
e52df44d0870a92b2a1efeb036a155a4c9c18ee7

Add docs page github action

DDegubi committed 4 years ago
Unverified
caa03ebd6cee1796999ee967178bcc686a25520a

Fix tests

DDegubi committed 4 years ago
Unverified
03786d9511284e4dfed9e8501ca2fe0c07a65fdf

Port project from js to python

DDegubi committed 4 years ago

README

The README file for this repository.

Python functional sequence processing library

Github issues Linecount GitHub Workflow Status Dependencies

  • The api is very similar to java8 streams
  • Lazy by default
  • Made because of boredom

Versions for other languages

Installation

Using pip:

pip install git+https://github.com/Degubi/Py-Seq.git

Without pip:

seq.py is available in the seq directory

Usage

Importing:

from seq import Sequence

Creating sequences:

Sequence.range(0, 10)                                    # 1 to 10 excluding 10
Sequence.range_closed(0, 10)                             # 1 to 10 including 10
Sequence.range(0, 10, 2)                                 # 1 to 10 stepping 2, excluding 10
Sequence.iterate(1, lambda k: k * 2)                     # 1, 2, 4, 8.... this sequence is infinite
Sequence.iterate(1, lambda k: k * 2, lambda k: k < 50)   # Same as the last one but taking values less than 50 (same as doing a takeWhile)
Sequence.generate(input)                                 # Generate strings with reading from console
Sequence.of(1, 3, 3, 7, 4, 2, 0)                         # Sequence of elements
Sequence.of([ 1, 2, 3 ])                                 # Create sequence from array

Transforming sequences (intermediate operations):

  • These operations do nothing by themselves, they only start doing work when the terminal operation gets called
  • Function list:

filter map flat_map distinct
take skip take_while skip_while
sort sort_ascending sort_descending chunk

  • Examples:
Sequence.range(0, 100)                 \  # Need to create a new sequence with every new pipeline
        .filter(lambda k: k % 2 == 0)  \  # Keep only even values in the sequence
        .map(lambda k: k * 2)          \  # Multiply them by 2
        .skip(2)                       \  # Skip the first 2 elements
        .take(10)                      \  # Take the first 10 elements only
        .sort_ascending()                 # Sort them in ascending order

Sequence.of({ 'prop1': 5, 'prop2': 'hey' }, { 'prop1': 5, 'prop2': 'ho'}, { 'prop1': 20, 'prop2': 'hi' }) \
        .distinct(lambda k: k['prop1'])        \  # Many functions have key selecting overloads, default is always identity
        .sort_descending(lambda k: k['prop1'])    # Same happens here

Sequence.of({ data: [ 1, 2, 3, 4 ] }, { data: [ 5, 6, 7, 8 ] })  \
        .flat_map(lambda k: k.data)                              \
        .take_while(lambda k: k < 6)

Finishing sequences (terminal operations):

  • Function list:

for_ach reduce to_list to_dictionary partition_by
sum count average min max
group_by first last join statistics
all_matches any_matches

  • Examples
seq = Sequence.range(0, 100)        # Let's assume we recreate this sequence every time

seq.for_each(print)                 # Print every value to the console
seq.reduce(0, lambda k, l: k + l)   # Sum all values
seq.sum()                           # Shorthand for summing
seq.count()                         # Count number of elements in sequence
seq.min()                           # Find the smallest value in the sequence, has key selector overload
seq.max()                           # Find the largest value in the sequence, has key selector overload
seq.average()                       # Average of the values in the sequence
seq.to_list()                       # Collect all elements into an array
seq.first()                         # Find the first element in the sequence, this returns the element or null
seq.last()                          # Find the last element in the sequence, this returns the element or null
seq.join(',')                       # Join elements with a comma
seq.statistics()                    # Returns an object with sum, count, min, max, average properties

seq = Sequence.of({ 'prop1': 5, 'prop2': 'hey' }, { 'prop1': 20, 'prop2': 'hi' }, { 'prop1': 20, 'prop2': 'hey' })

# Creates an object where the keys are from 'prop1' and the corresponding values are from 'prop2'
# Note: This call throws an error because of the duplicate 'prop1: 20' key
seq.to_dictionary(lambda k: k['prop1'], lambda k: k['prop2'])

# This is the same as the last example, but this version handles the duplicate key problem by keeping the first value
seq.to_dictionary(lambda k: k['prop1'], lambda k: k['prop2'], lambda key, previousValue, currentValue: previousValue)

# Returns true if the given predicate is true for all elements of the sequence
seq.all_matches(lambda k: k['prop1'] > 0)

# Returns true if the given predicate is true for any of the elements of the sequence
seq.any_matches(lambda k: k['prop2'] == 'nope')

# Groups elements by 'prop1' where the values are the objects that had the same key
seq.group_by(lambda k: k['prop1'])

# This does the same as the last example
seq.group_by(lambda k: k['prop1'], Grouper.to_list())

# Groups elements prop1' where the value is the frequency of the key
seq.group_by(lambda k: k['prop1'], Grouper.counting())

# Groups elements by 'prop2' where the value is the sum of 'prop1'
seq.group_by(lambda k: k['prop2'], Grouper.summing(lambda k: k['prop1']))

# First array contains the elements where the predicate was true
matching, notMatching = seq.partition_by(lambda k: k['prop1'] % 2 == 0)