Я знаком со стандартными zipWith
функциями, которые работают с соответствующими элементами двух последовательностей, но на функциональном языке (или языке с некоторыми функциональными особенностями), который является наиболее кратким способом условно выбрать пары элементов для архивирования, основываясь на третьей последовательности?
Это любопытство возникло при вычеркивании нескольких вещей в Excel.
С числами в A1: A10, B1: B10, C1: C10, D1, E1 и F1, я использую формулу, подобную этой:
{=AVERAGE(IF((D1<=(A1:A10))*((A1:A10)<=E1),B1:B10/C1:C10))}
Каждая половина умножения в операторе IF будет создавать массив логических значений, которые затем умножаются (AND). Эти булевы значения определяют, какой из десяти факторов будет в конечном итоге усреднен, так что, как будто оцениваются десять отдельных операторов IF.
Если, например, только второе и третье из 10 значений в A1: A10 удовлетворяют условиям (как> = D1, так и <= E1), то формула в итоге оценивается следующим образом: </p>
AVERAGE(FALSE,B2/C2,B3/C3,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE)
Функция AVERAGE игнорирует логические и текстовые значения, поэтому мы просто получаем среднее значение второго и третьего коэффициентов.
Может ли это быть сделано кратко с помощью Haskell? Erlang? LINQ или F #? Python? и т.д ..
ОБРАТИТЕ ВНИМАНИЕ, что для этого конкретного примера приведенная выше формула не совсем верна - она была сокращена для объяснения сути. Если ни один из десяти элементов в A1: A10 не удовлетворяет условиям, тогда десять значений FALSE будут переданы в AVERAGE, который неверно оценивается как 0.
Формула должна быть написана так:
{=AVERAGE(IF(NOT(OR((D1<=(A1:A10))*((A1:A10)<=E1))),NA(),
IF((D1<=(A1:A10))*((A1:A10)<=E1),B1:B10/C1:C10)))}
Где NA()
выдает ошибку, указывающую, что среднее значение не определено.
Обновление:
Спасибо за ответы. Я понял, что мой первый вопрос был довольно тривиальным с точки зрения применения функции к парам элементов из второго и третьего списков, когда соответствующий элемент из первого списка удовлетворяет некоторым конкретным критериям. Я принял ответ Нормана Рэмси за это.
Однако, когда я перешел к следующему, мне было интересно, можно ли применить эту функцию к кортежу, представляющему соответствующие элементы из произвольного числа списков - отсюда мой вопрос к Лебертраму о пределах zipWithN
.
Информация Apocalisp о аппликативных функторах привела меня к информации о распаковке списков аргументов в python - применении функции к произвольному числу аргументов.
Для конкретного примера, который я привел выше, усредняя отношения элементов списков (где nums
- список списков), похоже, что python может сделать это так:
from operator import div
def avg(a): return sum(a,0.0)/len(a)
avg([reduce(div,t[1:]) for t in zip(*nums) if d<=t[0] and t[0]<=e])
В более общем случае с функцией f
и предикатом p
(вместе с avg
) это становится:
avg([f(t[1:]) for t in zip(*nums) if p(t[0])])