Reduce(function(x, y) x + replace(y, is.na(y), 0), mylist)/
Reduce(`+`, lapply(mylist, function(x) !is.na(x)))
# x y
#1 2 3.5
#2 3 4.0
ИЛИ
nm = c("x", "y") # could do `nm = names(mylist[[1]])`
sapply(nm, function(NM)
rowMeans(do.call(cbind, lapply(mylist, function(x) x[NM])), na.rm = TRUE))
# x y
#[1,] 2 3.5
#[2,] 3 4.0
При передаче динамического массива как параметра не-var компилятор сделает копию.
Маленький пример кода ниже демонстрирует это путем отображения 37/42 в подписи формы.
procedure IncArray1(data: array of integer);
var i : integer;
begin
for i := Low(data) to High(data) do
data[i] := data[i] + 5;
end;
procedure IncArray2(var data: array of integer);
var i : integer;
begin
for i := Low(data) to High(data) do
data[i] := data[i] + 5;
end;
procedure TForm8.FormCreate(Sender: TObject);
var
data: array of integer;
begin
SetLength(data, 1);
data[0] := 37;
IncArray1(data);
Caption := IntToStr(data[0]);
IncArray2(data);
Caption := Caption + '/' + IntToStr(data[0]);
end;
Если мы изучаем сгенерированный ассемблерный код, IncArray1 запускается с
004552B4 8BCA mov ecx,edx
004552B6 85C9 test ecx,ecx
004552B8 7807 js $004552c1
004552BA 8B1C88 mov ebx,[eax+ecx*4]
004552BD 49 dec ecx
004552BE 53 push ebx
004552BF 79F9 jns $004552ba
004552C1 8BC4 mov eax,esp
Этот код копирует исходный массив в стек и устанавливает eax на адрес первого элемента (= адрес, сохраненный в указателе вершины стека после последнего нажатия). Стек углубляется так, код запускается с последнего элемента (edx, содержит Высокий (данные), когда IncArray1 называют) и повторения (элемент чтения; продвиньте элемент; постепенно уменьшите индекс), пока это не доберется до элемента 0.
IncArray2 не содержит такого кода. Вызывающая сторона хранит адрес данных в регистр eax прежде, чем назвать IncArray2, и IncArray2 просто использует этот адрес.
В случае, если Вы не хотите использовать 'var' по любой причине, можно передать адрес данных к методу. Но поскольку Вы не можете использовать синтаксис 'данные: ^array целого числа' в объявлении параметра, необходимо было бы объявить тип для данных. И необходимо было бы использовать 'data^' вместо 'данных' везде в методе.
type
TData = array of integer;
PData = ^TData;
procedure IncArray(data: PData);
var i : integer;
begin
for i := Low(data^) to High(data^) do
data^[i] := data^[i] + 5;
end;
procedure TForm8.FormCreate(Sender: TObject);
var
data: TData;
begin
SetLength(data, 2);
data[0] := 37;
IncArray(@data);
Caption := IntToStr(data[0]);
end;
Протестированный с Delphi 2007.
Ответ Gabr корректен, но ключевой пункт прокладывается под землей достаточно глубоко, что я произведу его как отдельное сообщение:
Определите свои типы сначала! В этом конкретном случае компилятор принял массив целого числа там, но это - то, только потому, что это имеет особое значение, и это не то, что Вы ожидали. Любая другая попытка определить тип в определении процедуры просто перестала бы работать.
В отличие от C, если Вы хотите две вещи быть присвоением, совместимым, необходимо объявить их как являющийся ТЕМ ЖЕ типом, не просто двумя типами, которые создаются то же:
Var
A : Array [1..4] of Integer;
B : Array [1..4] of Integer;
Begin
A := B;
Не скомпилирует. Скорее:
Type
Array4 = array [1..4] of Integer;
Var
A : Array4;
B : Array4;
Begin
A := B;
и компилятор делает то, что Вы ожидали бы.