Added pick and select for lists
Pick: (1 2 3 4)?4 or (1 2 3 4)?(3 2) Select: (1 2 3 4)~2 or (1 2 3 4)~(2 3)
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
from dataclasses import dataclass, field, replace
|
from dataclasses import dataclass, field, replace
|
||||||
from itertools import product
|
from itertools import product
|
||||||
from math import floor
|
from math import floor
|
||||||
|
import random
|
||||||
from types import LambdaType
|
from types import LambdaType
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import operator
|
import operator
|
||||||
@ -403,6 +404,47 @@ class ListOperation(Sequence):
|
|||||||
|
|
||||||
return flattened_list
|
return flattened_list
|
||||||
|
|
||||||
|
def _pick_from_list(left, right, options):
|
||||||
|
"""Pick random numbers from a list"""
|
||||||
|
if isinstance(left, Sequence):
|
||||||
|
left = _filter_operation(left, options)
|
||||||
|
|
||||||
|
if isinstance(right, Sequence):
|
||||||
|
right = _filter_operation(right, options)
|
||||||
|
|
||||||
|
if not isinstance(right, (list, Sequence)):
|
||||||
|
right = Sequence(values=[right])
|
||||||
|
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for num in right.values:
|
||||||
|
for _ in range(num.get_value(options)):
|
||||||
|
result.append(random.choice(left.values))
|
||||||
|
return flatten(result)
|
||||||
|
|
||||||
|
|
||||||
|
def _select_from_list(left, right, options):
|
||||||
|
"""Select number of items from shuffled list"""
|
||||||
|
if isinstance(left, Sequence):
|
||||||
|
left = _filter_operation(left, options)
|
||||||
|
|
||||||
|
if isinstance(right, Sequence):
|
||||||
|
right = _filter_operation(right, options)
|
||||||
|
|
||||||
|
if not isinstance(right, (list, Sequence)):
|
||||||
|
right = Sequence(values=[right])
|
||||||
|
|
||||||
|
result = []
|
||||||
|
left = left.values
|
||||||
|
|
||||||
|
for num in right.values:
|
||||||
|
random.shuffle(left)
|
||||||
|
num = num.get_value(options)
|
||||||
|
new_list = [left[i % len(left)] for i in range(num)]
|
||||||
|
result += new_list
|
||||||
|
|
||||||
|
return flatten(result)
|
||||||
|
|
||||||
def _vertical_arpeggio(left, right, options):
|
def _vertical_arpeggio(left, right, options):
|
||||||
"""Vertical arpeggio operation, eg. (135)@(q 1 2 021)"""
|
"""Vertical arpeggio operation, eg. (135)@(q 1 2 021)"""
|
||||||
left = _filter_operation(left, options)
|
left = _filter_operation(left, options)
|
||||||
@ -537,8 +579,13 @@ class ListOperation(Sequence):
|
|||||||
left = _vertical_arpeggio(left, right, options)
|
left = _vertical_arpeggio(left, right, options)
|
||||||
elif operation == "horizontal":
|
elif operation == "horizontal":
|
||||||
left = _horizontal_arpeggio(left, right, options)
|
left = _horizontal_arpeggio(left, right, options)
|
||||||
if operation == "zip":
|
elif operation == "zip":
|
||||||
left = _cyclic_zip(left, right, options)
|
left = _cyclic_zip(left, right, options)
|
||||||
|
elif operation == "pick":
|
||||||
|
left = _pick_from_list(left, right, options)
|
||||||
|
elif operation == "select":
|
||||||
|
left = _select_from_list(left, right, options)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
left = _python_operations(left, right, options)
|
left = _python_operations(left, right, options)
|
||||||
return left
|
return left
|
||||||
|
|||||||
@ -62,7 +62,9 @@ OPERATORS = MappingProxyType({
|
|||||||
">>": operator.irshift,
|
">>": operator.irshift,
|
||||||
"@": "vertical",
|
"@": "vertical",
|
||||||
"#": "horizontal",
|
"#": "horizontal",
|
||||||
"<>": "zip"
|
"<>": "zip",
|
||||||
|
"?": "pick",
|
||||||
|
"~": "select"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -431,7 +431,7 @@ class ZiffersTransformer(Transformer):
|
|||||||
def lisp_operation(self, items):
|
def lisp_operation(self, items):
|
||||||
"""Parse lisp like list operation"""
|
"""Parse lisp like list operation"""
|
||||||
op = items[0]
|
op = items[0]
|
||||||
values = items[1:]
|
values = items[2]
|
||||||
return LispOperation(
|
return LispOperation(
|
||||||
operator=op,
|
operator=op,
|
||||||
values=values,
|
values=values,
|
||||||
|
|||||||
@ -73,7 +73,6 @@ def zparse(expr: str, **opts) -> Ziffers:
|
|||||||
parsed.init_opts(opts)
|
parsed.init_opts(opts)
|
||||||
return parsed
|
return parsed
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -56,8 +56,9 @@
|
|||||||
right_op: list | number
|
right_op: list | number
|
||||||
// Operators that work only on lists: | << >>
|
// Operators that work only on lists: | << >>
|
||||||
list_operator: /(\||<<|>>|<>|#|@)(?=[(\d])/
|
list_operator: /(\||<<|>>|<>|#|@)(?=[(\d])/
|
||||||
|
// /(\||<<|>>|<>|#|@)(?=[(\d])/
|
||||||
// Common operators that works with numbers 3+5 3-5 etc.
|
// Common operators that works with numbers 3+5 3-5 etc.
|
||||||
operator: /([\+\-\*\/%\&])/
|
operator: /(\+|-|\*|\/|%|&|\?|~)/
|
||||||
|
|
||||||
// Euclidean cycles
|
// Euclidean cycles
|
||||||
// TODO: Support randomization etc.
|
// TODO: Support randomization etc.
|
||||||
@ -66,7 +67,8 @@
|
|||||||
?euclid_operator: /<[0-9]+,[0-9]+(,[0-9])?>/
|
?euclid_operator: /<[0-9]+,[0-9]+(,[0-9])?>/
|
||||||
|
|
||||||
// Lisp like list operation
|
// Lisp like list operation
|
||||||
lisp_operation: "(" operator WS sequence ")"
|
lisp_operator: /([\+\-\*\/%\&])/
|
||||||
|
lisp_operation: "(" lisp_operator WS sequence ")"
|
||||||
|
|
||||||
// Subdivision
|
// Subdivision
|
||||||
subdivision: "[" subitems "]"
|
subdivision: "[" subitems "]"
|
||||||
|
|||||||
Reference in New Issue
Block a user