Цитата |
---|
lostandleft написал: Немного более масштабный, и несколько менее удобый чем: |
краткость кода <> правильность и быстродействие.
Цитата |
---|
lostandleft написал: просто передать условие true false |
простите, у вас каша.
Цитата |
---|
lostandleft написал: True False как результат от вычислений (совершенно не обязательно связанных с конкретными столбцами), |
Каких вычислений? Не бывает абстрактных "вычислений", то есть вычислений "вообще". Есть конкретные вычисления. Эти конкретные вычисления должны быть где-то прописаны. Сравнение чего-то с чем-то (типа [Новый]=6) тоже вычисление. Но вы не хотите его прописывать - вы хотите передать результат - true/false, но он откуда берется?
Цитата |
---|
lostandleft написал:
Цитата |
---|
PooHkrd написал: В разных местах кода требуется один и тот же обработчик - выносим его в функцию чтобы сократить код. |
Именно так и есть!!! |
Так в том то все и дело, что у вас
обработчик не один и тот же, а разный! Как должен выглядеть обработчик неизвестного условия? Сейчас у вас это А-Б=1, затем это Б>5, потом у вас это "Б начинается с А и заканчивается В". Это совершенно разная проверка, разный код обработчика. Серьезно, даже странно это объяснять.
Не бывает универсальных обработчиков, практически. Приведенный мною код неэффективен, он будет долго работать, так как для каждой строки таблицы он будет делать лишнее действие, замедляющее его очень сильно, даже боюсь сравнивать.
Код, который привел
Андрей VG в #4, как раз и позволяет сделать так, чтобы в вашу функцию замены столбца передавался тот обработчик, который нужен в конкретном случае. Но сделать быстрый обработчик, который будет еще и угадывать мысли - ну нет.
Разобраться с функциями и конкретно этим кейсом - не сложно. Но для начала вам надо разобраться с работой встроенных функций.
подробное объяснение под катом |
---|
Вот у вас функция добавления столбца Table.AddColumn. Она работает построчно, добавляя новый столбец посредством функции (третий аргумент), которая по умолчанию принимает на вход единственный параметр - текущую строку в виде записи (record). Вы, конечно, можете написать свою функцию с большим количеством аргументов, но от Table.AddColumn в нее передастся все равно только один аргумент, а остальным взяться неоткуда (разве что снаружи от Table.AddColumn, см ниже).
В общем случае обращение к полю записи производится вот так: имязаписи[имя поля]. Table.AddColumn по умолчанию передает в функцию запись с именем _. А оператор each позволяет сделать две вещи: опустить определение функции (вот такое: (_)=> ) и при обращении к полю опустить использование имени записи в виде _, обращаясь непосредственно по имени поля: each [Новый]*5 Вот три абсолютно идентичных варианта кода функции Table.AddColumn:Код |
---|
=Table.AddColumn(Table, "New", each [столбец 19]*3,141529)
=Table.AddColumn(Table, "New", (_)=>_[столбец 19]*3,141529)
=Table.AddColumn(Table, "New", (row)=>row[столбец 19]*3,141529) |
Во всех случаях обращение к [столбец 19] жестко записано в коде функции. Если вы хотите, чтобы имя столбца было переменной, которая откуда-то поступает в эту функцию, вы уже не можете записать [переменная] - нет такого поля в записи, нужно другое обращение. Это обращение вот такое: Код |
---|
Record.Field(record, имяполя как текст) |
эта функция получает значение поля с именем имяполя в записи record Соответственно у вас функция с 4 аргументами (имятаблицы, старый, новый, условие), которая должна работать как "добавляем столбец так, что если условие истинно, то берем новый, иначе берем старый) Код |
---|
=(таблица as table, старый as text, новый as text, условие as logical)=>
Table.AddColumn(таблица, "tmp", each if условие then Record.Field(_, новый) else Record.Field(_, старый))) |
если условие - это уже рассчитанное true/false, то оно рассчитано заранее и будет одно и то же для любой строки, и городить огород вообще незачем. Но если условие должно принимать значение true/false в зависимости от строки, то его нельзя рассчитывать заранее, оно должно рассчитываться, принимая текущие значения новый и старый для каждой строки. Значит, условие должно стать функцией, возвращающей true/false, и принимающей на вход два имени столбца:Код |
---|
=(таблица as table, старый as text, новый as text, условие as function)=>
Table.AddColumn(таблица, "tmp", each if условие(старый, новый) then Record.Field(_, новый) else Record.Field(_, старый))) |
Но теперь нам эту функцию надо задать, указав в ней правило получения true/false:Код |
---|
условие = (старый as text, новый as text) as logical => Record.Field(_, новый)-Record.Field(_, старый)=1 |
как видите, я здесь использую _, потому что функция условие найдет эту переменную снаружи от себя - это то самое имя записи/строки, которое передало в свой третий аргумент Table.AddColumn Теперь, надеюсь, понятно, почему не может быть абстрактной проверки условий. Вы прокомментировали, что как же так - неужели на каждое условие надо будет писать свою отдельную функцию? Андрей VG вам в #4 показал, как можно сделать, не создавая такие функции заранее, а указывая функцию при вызове вашей большой функции.
Теперь, надеюсь, совсем понятно. |