262 подписчика
Фильтрация списка по списку через словарь и Splitter
#АнатомияФункций - Record.FieldOrDefault, Splitter.SplitTextByRanges
Всем привет!
Итак, задачка – «отфильтровать один список по частичным совпадениям начала строк со вторым».
Делов-то:
let
lst = Excel.CurrentWorkbook(){[Name="tsrc"]}[Content][col],
dict = List.Buffer(Excel.CurrentWorkbook(){[Name="tmatch"]}[Content][match]),
to = List.Select(lst,(x)=>List.Contains(dict,x,(y)=>Text.StartsWith(x,y)))
in
to
Только проблема… медленно это. И вот приходит такой Андрей (m) и выкатывает:
let
lst = List.Buffer(Excel.CurrentWorkbook(){[Name="tsrc"]}[Content][col]),
dict = List.Buffer(Excel.CurrentWorkbook(){[Name="tmatch"]}[Content][match]),
to = List.Transform(List.PositionOfAny(lst,dict,Occurrence.All,(c,v)=>Text.StartsWith(c,v)),(x)=>lst{x})
in
to
А я говорю – да нет, тогда уж вот:
let
lst = List.Buffer(Excel.CurrentWorkbook(){[Name="tsrc"]}[Content][col]),
dict = List.Buffer(Excel.CurrentWorkbook(){[Name="tmatch"]}[Content][match]),
to = List.Transform(List.PositionOfAny(lst,dict,Occurrence.All,Text.StartsWith),(x)=>lst{x})
in
to
А тут ещё Игорь (CubRoot) приходит, говорит вот так надо:
let
lst = Excel.CurrentWorkbook(){[Name="tsrc"]}[Content][col],
dict = List.Buffer(Excel.CurrentWorkbook(){[Name="tmatch"]}[Content][match]),
to = List.Select(lst,(x)=>Splitter.SplitTextByAnyDelimiter(dict)(x){0}="")
in
to
А я такой – блин, да нет же – вот так надо:
let
lst = Excel.CurrentWorkbook(){[Name="tsrc"]}[Content][col],
dic = Excel.CurrentWorkbook(){[Name="tmatch"]}[Content][match],
len = List.Buffer(List.Distinct(List.Transform(dic,Text.Length))),
dict = Record.FromList(List.Repeat({true},List.Count(dic)),dic),
f=(x)=>List.AnyTrue(List.Transform(len,(y)=>Record.FieldOrDefault(dict,Text.Start(x,y)))),
to = List.Select(lst,f)
in
to
... а сам думаю, но ведь со сплиттером-то и правда вкуснее:
let
lst = Excel.CurrentWorkbook(){[Name="tsrc"]}[Content][col],
dic = Excel.CurrentWorkbook(){[Name="tmatch"]}[Content][match],
len = List.Buffer(List.Distinct(List.Transform(dic,(x)=>{0,Text.Length(x)}))),
dict = Record.FromList(List.Repeat({true},List.Count(dic)),dic),
f=(x)=>List.AnyTrue(List.Transform(Splitter.SplitTextByRanges(len)(x),(y)=>Record.FieldOrDefault(dict,y))),
to = List.Select(lst,f)
in
to
И вот так долго ли коротко ли скорость выполнения была приподнята в 15 раз )))
А как оно так – смотрим на дзене
Исходники с бонусными вариантами на sponsr
Лайки, комменты, подписки приветствуются )))
Надеюсь, было полезно.
Всех благ!
2 минуты
19 августа 2024