Страницы: 1
RSS
PQ. Проверка списков на одинаковое количество значений ( "длина" списка), оптимальный способ (по времени исполнения) проверки n-ого количества списков
 
Вечер добрый.
Для решения задачи на вход подается список состоящий из списков.
Прежде чем приступить к обработке, требуется провести проверку на "длину" каждого из списков, т.е. { {список1}, {список2}, ... , {список-n} } должны содержать одинаковое количество числовых значений.
Просмотрев функции работы со списками я накидал несколько способов, но так как не очень знаком с механизмами исполнения PQ хотелось бы узнать ваше мнение на скорость обработки, если например будет 10-20к значений в каждом списке, самих списков не очень много: 10-15.
Код
let
    input = { {8.5, 9.5, 9.9, 9.0}, {0.65, 0.8, 0.8, 0.9}, {1.2, 1.3, 0.5, 0.6} },
    number_of_items = List.Transform( input, each List.Count ( _ ) ),
    check_0 = List.AllTrue ( List.Transform( number_of_items, each _ = List.Average( number_of_items ) ) ),
    check_1 = List.Count( List.Distinct( number_of_items ) ) = 1,
    check_2 = List.MatchesAll( number_of_items, each _ = List.Max( number_of_items ) ),
    check_3 = List.StandardDeviation( number_of_items ) = 0,
    check_4 = List.Contains( { List.Zip( input ) }, null ),
    output = [check_average = check_0, check_distinct = check_1, check_matchesall = check_2, check_deviation = check_3, check_contains = check_4]
in
    output
 
Доброе время суток.
Теоретически можно чуть ускорить
Код
let
    input = { {8.5, 9.5, 9.9, 9.0}, {0.65, 0.8, 0.8, 0.9}, {1.2, 1.3, 0.5, 0.6} },
    number_of_items = List.Buffer(List.Transform( input, List.Count)),
    first = number_of_items{0},
    isEqualCount = not List.MatchesAny(number_of_items, (item) => item <> first)
in
    isEqualCount

но, учитывая
Цитата
DrillPipe написал:
самих списков не очень много: 10-15.
без особой разницы
Код
let
    input = { {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300000}, {1..300001} },
    number_of_items = List.Buffer(List.Transform( input, List.Count)),
    first = number_of_items{0},
    isEqualCount = not List.MatchesAny(number_of_items, (item) => item <> first)
in
    isEqualCount
не заметно, чтобы Power Query о чём то думал.
 
Андрей VG,
Спасибо большое, коллега!
 
Цитата
DrillPipe написал:
числовых значений
А я поначалу подумал что еще и вот это условие таки нужно проверять. Не надо было, да? В списках всегда будут только числа, без инородных элементов и null?
А так то можно еще сравнить Max и Min значения.
Код
let
    input = { {8.5, 9.5, 9.9, 9.0}, {0.65, 0.8, 0.8, 0.9}, {1.2, 1.3, 0.5, 0.6} },
    number_of_items = List.Buffer(List.Transform( input, List.Count)),
    isEqualCount = List.Max(number_of_items) = List.Min(number_of_items)
in
    isEqualCount
Изменено: PooHkrd - 16.04.2020 23:46:53
Вот горшок пустой, он предмет простой...
 
Можно еще так, для разнообразия, но на скорость не проверял
Код
= List.Count(List.Distinct(List.Transform(input, List.Count)))=1

вариант PooHkrd представляется самым быстрым, хотя, кмк, это ловля блох
Изменено: Максим Зеленский - 17.04.2020 10:18:04 (поторопился)
F1 творит чудеса
 
Цитата
Максим Зеленский написал:
это ловля блох
Согласен, основной ресурс все равно уйдет на подсчет элементов во внутренних списках, а не на вычисление отклонений в списке из 10-15 элементов. Хотя, конечно, там есть у ТС пара-тройка вариантов перебора элементов списка, в которых ленивка наверняка подложит ему свинью если делать без буфера.
Вот горшок пустой, он предмет простой...
 
упс. проглядел, что у ТС уже есть это
Код
check_1 = List.Count( List.Distinct( number_of_items ) ) = 1,
F1 творит чудеса
 
Спасибо всем!
Поскажите, почему работает эта конструкция запроса?
Код
List.Transform( input, List.Count)

Ведь функция List.Coun вызывается без аргумента
 
DrillPipe, уже неоднократно тут разбиралось записи
Код
=List.Transform( input, each List.Count(_) )
=List.Transform( input, (x)=>List.Count(x) )
=List.Transform( input, (_)=>List.Count(_) )
=List.Transform( input, List.Count )

для данного случая равнозначны. Такие особенности синтаксиса языка, т.к. вторым аргументом в List.Transform должна выступать функция преобразования, которая будет применяться к каждому элементу списка, то можно не заморачиваться с each или с объявлением анонимной функци. Зачем? Если имеется уже готовая.
Изменено: PooHkrd - 18.04.2020 00:15:23
Вот горшок пустой, он предмет простой...
 
Здравствуйте
до кучи, так сказать
Код
let
    input  = { {8.5, 9.5, 9.9, 9.0}, {0.65, 0.8, 0.8, 0.9}, {1.2, 1.3, 0.5, 0.6} },
    check  = (d)=>(e)=>e(d)=e(List.Generate(()=>[a=0,b=e(d{0}),c=true],each if [a]<e(d) then [c] else false, each [a=[a]+1,b=e(d{a}),c=b=[b]]))
in
    check(List.Buffer(input))(List.Count)
Изменено: Андрей Лящук - 18.04.2020 21:49:08
Страницы: 1
Наверх