У вас может быть что-то подобное
enum C1 {
WITH_PARAM("value"),
EMPTY();
private String value;
C1(String s) {
System.out.println("with param = " +s);
value=s;
}
C1() {
System.out.println("without param");
}
public void g() {
System.out.println("inside g, value is "+value);
}
}
public static void main(String s[]) {
C1.EMPTY.g();
C1.WITH_PARAM.g();
}
. в функциональном смысле это комбинация:
взять две последовательности и создать последовательность кортежей элементов
и
Take функция f
и последовательность и возвращают новую последовательность, которая является f (x) для каждого x в исходной последовательности
Индекс тривиален в c # 4.0 Если взять упрощенную реализацию, у нас есть
static class Enumerable
{
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> func)
{
var ie1 = first.GetEnumerator();
var ie2 = second.GetEnumerator();
while (ie1.MoveNext() && ie2.MoveNext())
yield return func(ie1.Current, ie2.Current);
}
}
. Затем нам нужна карта. У нас это уже есть, это то, что мы называем Select в c #
IEnumerable<int> input = { 1,2,3,4 };
int a = 0;
var accumulate = input.Select(x =>
{
a += x;
return a;
});
Но безопаснее запекать это в свой собственный метод (без каррирования в c #) и разрешать поддержку произвольных типов / накоплений.
static class Enumerable
{
public static IEnumerable<T> SelectAccumulate<T>(
this IEnumerable<T> seq,
Func<T,T,T> accumulator)
{
var e = seq.GetEnumerator();
T t = default(T);
while (e.MoveNext())
{
t = accumulator(t, e.Current);
yield return t;
}
}
}
Затем мы можем собрать их вместе например,
var input = new int[] {1,2,3};
var mapsum = input.Zip(
input.SelectAccumulate((x,y) => x+y),
(a,b) => new {a,b});
Это будет повторять последовательность дважды, но это более общее. Вы можете сделать аккумулятор самостоятельно в рамках стандартного выбора и простого замыкания, но он больше не так полезен, как «строительный блок», являющийся одной из движущих сил функционального программирования.
Поддержка кортежей - это боль, кроме как внутри метод как анонимные типы не пересекает границы метода без особых хлопот. Несколько основных кортежей должны быть включены в c # 4.0. предполагая, что класс / структура кортежа называется Pair
Я думаю, что это самый короткий подход:
int sum = 0;
var result = input.Select(i => new { i, S = sum += i });
int runningTotal=0;
var p = input.Select((l)=>
{
runningTotal+=l;
return new {l,Total=runningTotal};
});
Foreach всегда будет в порядке. Откройте отражатель и посмотрите на ForEach в списке (ForEach не существует в массиве), но все, что делает ForEach - это цикл for для элементов.
Я не уверен насчет select, насколько я знаю но я никогда не копался в этом.
var input = new int[] {1,2,3}
var output = new List<KeyValuePair<int,int>>();
int runningTotal = 0;
foreach (int current in input)
{
runningTotal += current;
output.Add(new KeyValuePair(current, runningTotal);
}
Было бы легко преобразовать это в функцию Linq .Foreach (), если вы действительно этого хотите. проблема будет в том, если вы не хотите иметь отдельный промежуточный итог.
функциональная версия:
intput.Foreach(current=>
{
runningTotal += current;
output.Add(new KeyValuePair(current, runningTotal);
}
);
var output = input.Select((i, indexI) =>
new {
Element = i,
RunningSum = input.Where((j, indexJ) => indexJ <= indexI).Sum()
});
Это будет получить коллекцию анонимного типа с двумя свойствами Element и RunningSum.
UPDTAE
Вот еще одно решение, использующее только метод расширения LINQ Aggregate. И да, это ужасно.
var output = input.Aggregate(
new List<KeyValuePair<Int32, Int32>>(),
(result, element) =>
{
result.Add(new KeyValuePair<Int32, Int32>(
element,
element + result.LastOrDefault().Value));
return result;
});
Functional implementation (no side effects) and no extensions:
internal struct Tuple<T> {
public T A;
public T B;
}
internal class Program {
private static void Main(string[] args) {
var ints = new[] { 5, 7, 11, 13 };
IEnumerable<Tuple<int>> result = ints.Aggregate<int, IEnumerable<Tuple<int>>>(new List<Tuple<int>>(),
(sum, item) => sum.Concat(new[] { new Tuple<int> { A = sum.LastOrDefault().A + item, B = item } }));
Console.WriteLine(string.Join(" ", result.Select(item => "(" + item.A + "," + item.B + ")").ToArray()));
}
}
Though can't figure out how to make it with anonymous type instead of Tuple. Также может быть упрощено, если будет:
IEnumerable<T> Append(this IEnumerable<T> @this, T item);
Просто для забавы, здесь это в F # с использованием встроенной функции Seq.scan:
> let input = [1;2;3];;
val input : int list
> input |> Seq.scan (fun (_, acc) x -> (x, acc + x)) (0,0) |> Seq.skip 1;;
val it : seq<int * int> = seq [(1, 1); (2, 3); (3, 6)]