Tempo de leitura:
Neste artigo vou mostrar-te a função List.Accumulate! Uma função extraordinária que permite realizar loops sobre uma lista!
A função funciona como um iterador, ou seja, percorre os itens de uma lista, executando uma determinada ação em cada item, mas ao contrário de um iterador normal, esta função tem memória! Guarda o estado (state) da última iteração.
Ao ser executada esta função acede ao item atual da lista e ao resultado da última iteração, na operação realizada, a função usa o resultado da operação como o input para o próximo passo da iteração.
Parece confuso, mas o processo é bastante simples!
Sintaxe da função
Vamos começar por conhecer a sintaxe da função!
List.Accumulate (
List as list,
Seed as any,
Accumulator as function )
Que significa o seguinte:
List.Accumulate (
List as list, // Lista a iterar
Seed as any, // valor inicial
Accumulator as function ) // Operação realizada
- List: A lista para a função. A função List.Accumulate itera (percorre) cada valor na lista enquanto aplica a função acumuladora (Accumulator)
- Seed: Este é apenas o ponto de partida, que pode ser um valor, uma lista, ou até uma tabela.
- Accumulator: A operação a realizar, com as instruções necessárias para a função executar para cada item da lista. A função acumuladora tem 2 argumentos -> State e Current. Os nomes podem ser dados conforme o que o utilizador pretende.
- State é o valor acumulado, que começa com o valor inicial (seed).
- Current é o valor / item atual da lista.
Depois de executada a 1ª iteração o “state” deixa de ser (seed) e passa a ser o último valor da operação acumuladora (a memória) que é executada com o próximo item da lista! E assim sucessivamente até terminar a lista!
Exemplo 1: List.Acumulate simples
Neste primeiro exemplo vamos perceber o resultado que sai da função. Esta questão é importante, pois está relacionado com o parâmetro seed. Seed é o valor inicial, que como indicado na descrição pode ser um valor, uma lista, uma tabela, por exemplo. Isto significa que este ponto inicial é fundamental para perceberes a função. Se o seed for um valor, a função List.Accumulate devolve um valor, se for uma lista, devolve uma lista e por exemplo se for uma tabela, devolve uma tabela.
Exemplo da função:
No primeiro passo começamos por criar uma lista: = {1..5}
No passo seguinte, colocamos a expressão.
= List.Accumulate (
Origem,
1,
(state, current) => state + current
)

Como podes verificar, o resultado é um valor -> 16. A função está a acumular, fazendo uma simples soma entre o estado (state) e o valor atual (current). Mas como o valor inicial (seed) é um número, a função retorna um número.
Eis o processo mais visual…

O qual podes ver numa lógica do cálculo acumulativo realizado com uma operação simples em Excel.

E que resulta no valor 16.

O resultado é sempre o “resultado” do último passo!
Exemplo 2: List.Acumulate simples a devolver uma lista
O próximo exemplo é exatamente o mesmo, mas vamos devolver uma lista! Para devolver uma lista, na operação efetuada precisamos de ajustar alguns detalhes.
- A função acumuladora é -> estado (state) + atual (current): neste caso como o nosso estado inicial é uma lista, o estado também será uma lista. Não é possível somar uma lista com um valor. Desta forma a função acumuladora necessita de obter o último valor da lista (List.Last) para depois podermos somar ao valor atual da lista.
= List.Accumulate (
{1..5}, // Lista inicial
{1}, // Valor inicial em lista (seed)
(estado, atual) => estado & {List.Last(estado) + atual} //Resultado em Lista
)

Exemplo 3: List.Acumulate com texto
Quando temos uma lista de texto é também possível realizar um loop sobre a lista. E realizar operações. Este exemplo é semelhante aos anteriores, mas estamos a trabalhar com uma lista de texto.
= List.Accumulate (
Origem,
{“1”},
(estado, atual) => estado & {List.Last(estado) & “-” & atual}
)

Exemplo 4: List.Acumulate uma Tabela
O próximo exemplo já é um pouco mais aliciante pois vamos iniciar com uma Tabela. O seed é uma tabela, e consequentemente o resultado continuará a ser uma tabela!
Vamos começar por criar uma tabela simples em Power Query.

Imagina agora inserir uma coluna com o desconto de 10 % aplicado.

O resultado é o seguinte…

Mas o objetivo é, comparar vários descontos! Assim temos um exemplo perfeito para a função List.Accumulate, pois podemos ter os descontos numa lista, e acumular a criação de uma nova coluna, mantendo o estado (Tabela) como memória.
Depois de termos a Tabela e o exemplo do código base para criação da nova coluna. Vamos criar a lista a iterar.

Agora com a Função List.Accumulate, podemos criar uma coluna nova sobre cada um dos valores da lista. Apenas temos de fazer alguns ajustes ao código.
= List.Accumulate (
ListaDescontos,
Tabela,
(EstadoTabela, ColunaAtual) =>
Table.AddColumn(
EstadoTabela,
Text.From(ColunaAtual * 100) & “% Desconto”,
each [Valor] * ColunaAtual, type number
)
)
No cenário da função temos apenas as seguintes adaptações.
- EstadoTabela: Representa a nossa tabela
- Text.From(ColunaAtual * 100) & “% Desconto”: Apenas uma adaptação para colocar o nome da nova coluna mais dinâmico.
- ColunaAtual: Representa o valor atual da lista, e assim o desconto aplicado.

Exemplo 5: Iterar sobre as colunas de uma Tabela Existente
No último exemplo da função List.Accumulate vamos iterar sobre as colunas de uma Tabela já existente. O objetivo agora não é adicionar colunas, mas sim realizar uma transformação sobre todas as colunas.
Assim começamos por uma tabela.

Testamos a solução em primeiro lugar com uma coluna, para podermos adaptar mais facilmente o código. O teste será saber o parcial de cada departamento sobre o total global.
Uma vez que vamos usar as colunas como iterador, precisamos em primeiro lugar de uma lista com os nomes das colunas a iterar.
= List.Skip(Table.ColumnNames(Tabela), 1)

Agora, vamos testar realizar uma transformação numa coluna, por exemplo Janeiro, para obter o valor de cada departamento sobre o valor total.
= Table.TransformColumns (
Tabela,
{
{“Janeiro”, each _ / List.Sum(Tabela[Janeiro]), Decimal.Type}
})
Esta fórmula, da função Table.TransformColumns é a base para realizarmos a transformação a todas as restantes colunas.

Adaptar o código para a função List.Accumulate
Agora já temos todos os ingredientes para adaptar o código para a função List.Accumulate.
= List.Accumulate (
ListaNomes,
Tabela,
(EstadoTabela, ColunaAtual) =>
Table.TransformColumns (
EstadoTabela,
{
{ColunaAtual, each _ / List.Sum(Table.Column(EstadoTabela, ColunaAtual)), Percentage.Type}
}
)
)
Por uma questão de contexto de avaliação usamos aqui a função Table.Column para identificar a variável da tabela (EstadoTabela) e não a Tabela original a iterar.

Uma vez que a lista com os nomes da coluna da tabela, é variável e versátil, existindo novas colunas a iteração é direta!
Próximo artigo:
Artigo Anterior:
Ficheiros
Artigos por Categoria
- Microsoft Excel (41)
- Power Apps (16)
- Power Automate (3)
- Power BI (11)
- Power Query (12)
- Python (3)
- VBA (7)

Leave a Reply