Сделали ElementsByRow ElementsByCol ElementsWithIndexes SetRow SetCol Пример по ConvertAll:
begin
var a := Arr(2,3,4);
var b := a.ConvertAll(x->x+0.1);
b.Println
end.
Сделали ElementsByRow ElementsByCol ElementsWithIndexes SetRow SetCol Пример по ConvertAll:
begin
var a := Arr(2,3,4);
var b := a.ConvertAll(x->x+0.1);
b.Println
end.
Спасибо большое, все попробовал, работает. ElementsByRow и ElementsByCol - насколько я понял, можно воспринимать теперь, как синтаксический сахар:
Тем не менее, удобно и понятно, особенно для новичков на первых порах. По-моему, “mast have”
Осталось пара вещей, чтобы для подавляющего большинства задач с двумерными массивами уйти от циклов: распространить на матрицы срезы и как-то решить вопрос с операцией, обратной к ElementsBy - формированием матрицы из последовательности. Ведь тогда мы можем вытворять с матрицами потрясающие вещи, например, вычеркнуть строку или столбец, изменить размеры матрицы, поменять значения в некоторой группе элементов и т.п.
Теперь несколько не по теме этого сообщения. Понемногу делаю библиотеку для работы с матрицами. Именно матрицами в математическом смысле. попробовал перегрузить операции - получилось для сложения, вычитания и умножения. Произведений у матриц, как известно два: векторное и скалярное (я рассматриваю векторы, как матрицы, т.е. векторы-строки и векторы-столбцы). Векторное используется все же чаще и для него я сохранил традиционную операцию * А для скалярного начал думать, какой символ взять. Выяснил, что символы можно брать только от тех операций, которые уже определены в Паскале. В справке прочитал:
Перегружать можно все операции за исключением @ (взятие адреса), as, is, new. Кроме того, можно перегружать специальные бинарные операции +=, -=, *=, /=, не возвращающие значений. Перегружать можно только еще не перегруженные операции.
Не знаю, перегружена ли операция ^ , но этим символом воспользоваться не удалось. И еще, в справке увидел операцию => - это что?
Таблица приоритетов операций @, not, ^, +, - (унарные), new 1 (наивысший) *, /, div, mod, and, shl, shr, as, is 2 +, - (бинарные), or, xor 3 =, <>, <, >, <=, >=, in, => 4 ?: 5 (низший)
Вот это совсем не хочется делать в стандартной библиотеке. Эта операция - очень специфическая и черевата ошибками в случае несовпадения длин. Так что давайте оставим это пользователям
Это небезопасные операции. Как и превращение последовательности в матрицу.[quote=“RAlex, post:145, topic:1177”] И еще, в справке увидел операцию => - это что? [/quote]
Её уже нет. Уберем в следующей версии справки
Это будет означать лишь одно - невозможность решить большую часть задач без применения циклов. И тогда смысл всех этих манипуляций с матрицами в функциональном стиле становится не особо понятным: надо изучать приличный объем новаций, а все равно мы возвращается к циклу. Небезопасные операции… а давайте вспомним те же реляционные СУБД и взглянем на матрицу, как на таблицу. Сначала в SQL начали думать о выборках и появился “безопасный” SELECT. А потом пришли к тому. что нужны и INSERT, и DELETE, и UPDATE. И в работе с СУБД от SQL-выборки в “безопасные” курсоры read-only пришли к обновляемым курсорам. Ибо без этого слишком ущербно и однобоко получается.
Вот простая и достаточно характерная задача. В двумерном массиве, заполненном случайными целыми числами из интервала [10;50], заменить все элементы, расположенные между минимальным и максимальным значениями, на ноль. Матрицу рассматривать в порядке по строкам. Я не вижу другого разумного варианта, кроме циклов.
// PascalABC.NET 3.2, сборка 1415 от 25.03.2017
begin
var m,n:integer;
Read(m,n);
var a:=MatrRandom(m,n,10,50);
a.Println(3); Writeln;
var s:=a.ElementsByRow.ToArray;
var i1:=s.IndexMax;
var i2:=s.IndexMin;
if i1>i2 then Swap(i1,i2);
if i2-i1>1 then begin
var q:=(s[:i1+1]+ArrFill(i2-i1-1,0)+s[i2:]).ToArray;
for var i:=0 to m-1 do
for var j:=0 to n-1 do
a[i,j]:=q[n*i+j];
a.Println(3)
end
end.
Почему-то тут ностальгически вспомнился Fortran-IV, который позволял обращаться к n-мерному массиву, как к одномерному, используя так называемый “обобщенный индекс”.
В современных языках это не делается.
Стандартные библиотеки содержат только безопасные операции. Всё, что Вы перечисляете, относится к тому, старому миру, когда безопасности не придавали должного внимания.
Сейчас подобные методы реализует пользователь - никакая стандартная библиотека ответственность на себя не возьмёт. Или использует циклы.
Можно реализовать некоторые методы, которые преобразуют двумерный массив в такой же двумерный массив или выполняют операцию foreach.
Да хотя бы сделайте ConvertAll. Foreach - это ВЫБОРКА, а проблема в массовой модификации данных. Вот, пожалуйста, еще задача. Простейшая. А как без цикла?
Pascal. Двумерный массив. Получить новую матрицу путем деления всех элементов данной матрицы на ее наименьший по модулю элемент
Ненормально писать коды, подобные нижеследующему
for var i:=0 to a.RowCount-1 do
a.SetRow(i,(a.Row(i).Select(x->2*x)).ToArray);
Уж лучше тогда работать с матрицами в обычном “старом стиле”, забыв про функциональное программирование, В моей голове вполне укладывается концепция безопасности операций. Но выборка при этом может быть совершенно произвольной! Почему же не сделать возможности генерации некоего двумерного массива на базе последовательности? В чем тут опасность? Если длина последовательности k и мы желаем создать двумерный массив, содержащий n столбцов, неужели так невозможно найти число строк m = k div n и разрешить формирование, если k mod n = 0 ? Вовсе же нет необходимости вписываться в какой-то существующий массив или обеспечивать некий заранее заданный размер - все динамически вычисляется - и размер, и возможность создания.
Это всё чудесно делает NumPy в Python. Эти операции относятся к тому миру, в котором всё надо делать быстро. Если ваш “современный мир” не в состоянии обеспечить и эффективность, и безопасность, то всё пропало, мир пришёл не туда.
Посмотрю
А как бы Вы хотели?
Например, как-то вот так:
// PascalABC.NET 3.2, сборка 1415 от 25.03.2017
function MatrUnpack<T>(s:sequence of T;cols:integer):array[,] of T;
begin
var r:=new T[s.Count div cols,cols];
var n:=r.Length;
var k:=0;
foreach var elem in s do begin
r[k div cols, k mod cols]:=elem;
k+=1;
if k=n then break
end;
Result:=r
end;
function MatrUnpack<T>(Self:sequence of T;cols:integer):array[,] of T;
extensionmethod;
begin
var r:=new T[Self.Count div cols,cols];
var n:=r.Length;
var k:=0;
foreach var elem in Self do begin
r[k div cols, k mod cols]:=elem;
k+=1;
if k=n then break
end;
Result:=r
end;
begin
var a:=MatrRandom(4,5,10,50);
a.Println(3); Writeln;
var b:=a.ElementsByRow.Select(x->x.IsOdd?x+1:x-1).MatrUnpack(5);
b.Println(3)
end.
17 22 40 31 12
28 41 13 43 19
32 20 13 45 46
30 28 27 35 50
18 21 39 32 11
27 42 14 44 20
31 19 14 46 45
29 27 28 36 49
P.S. В качестве первого обзора NumPy
Сделал:
begin
var a := MatrRandom(2,3);
a.Println;
a.Transform(x->x+1);
a.Println;
var b := a.ConvertAll(x->x+0.1);
b.Println;
end.
Спасибо, уже хоть что-то! ))) По крайней мере можно хоть теперь заполнить вещественную матрицу случайными целыми …
Этого я точно не делал…
Просто напишите в своем примере var b := a.ConvertAll(x->x+0.0);
Заглянул в NumPy. Никогда меня Пайтон не увлекал, поскольку после давнишних мучений с позициями на перфокартах в Fortran-IV возникла стойкая идиосинкразия к языкам с синтаксисом, зависящим от отступов и позиций на строке исходного текста. Обнаружил две интересные функции - reshape, возвращающую массив с иным рангом (формой) и resize, выполняющую эту операцию с исходным массивом. Resize забраковал, будучи определенным образом солидарен с идеологией @Admin в части минимума “опасных” операций над исходными объектами в программе. Почему не полностью солидарен? Считаю, что любая идеология в языке программирования, если это не специализированный язык для особо надежных вычислений (как в свое время преподносился язык Ада, разрабатываемый по заказу министерства обороны США) не должна входит в противоречие с удобством программирования и тут поддерживаю высказанное выше @bravit А вот reshape() - именно то, что нужно “для полного счастья”. Ведь ничто не мешает написать a:=a.Reshape(…); В NumPy параметры reshape - это желаемые размерности возвращаемого массива, причем исходный массив рассматривается в порядке “по строкам”. Но есть занятная опция [,order=‘F’], которая рассматривает исходный массив в стиле Fortran, т.е. по столбцам.
А что, кстати, насчет современных реализаций языка Fortran? Оказывается, в нем тоже есть reshape(), только не в какой-то библиотеке, а прямо в реализации. И делает эта функция то же самое, что и в NumPy - меняет форму массива, На самом деле меня посетила мысль, что эту прекрасную функцию в NumPy просто “слизали” из Фортрана. А еще, есть у фортрановской reshape одна удобная, как теперь говорят, “фишка”. Если задать среди параметров количество элементов в некотором измерении в виде -1, то оно будет автоматически вычислено исходя из размеров исходного массива. Для двумерного массива это означает возможность явно задавать только длину по одному из измерений, что я нахожу весьма удобным.
Резюме: Современные реализации Fortran и библиотека NumPy для Python имеют функцию Reshape(), возвращающую исходный массив с измененной формой. В частности, она может сформировать массив нужной формы из одномерного массива. Может быть, все же стоит сделать такую же функцию (метод), работающую по следующим правилам:
Ну то есть, если коротко, Вы хотите Reshape для одномерных массивов для преобразования их в двумерные?
Как минимум. А вообще Reshape и для двумерных тоже:
И потом, наверно не совсем правильно говорить, что я этого для себя хочу: у меня есть библиотека, в которой это уже давно реализовано, может не так, как надо для общего случая, может криво в чем-то, но работает). Я предлагаю добавить в язык Reshape, чтобы дать возможность работать с матрицами в функциональном стиле, а не переходить к традиционным циклам. Чтобы и тут по простоте и удобству написания программы Паскаль вдруг не проиграл тому же Питону.
Можно, конечно, все это и не делать, но вот информация, поясняющая причину наличия в языках программирования операций not, or, and, xor… а не одной единственной стрелки Пирса:
(по материалам Интернет)
Так есть же уже a.ElementsByRow. А a.Reshape с какими параметрами Вы собираетесь использовать чтобы преобразовать её к одномерному массиву?
a.Reshape(12) для преобразования в одномерный мне сильно не нравится. Я понимаю, что Вы решили объединить мух и котлет ради призрачной унификации. Претензии к этому решению - такие.