Forum Discussion
Does Text Contain All Words
- 5 years ago
Here is one way to do it with these two queries of your example data. It also shows you which Template had the match (bonus kudos?). To see how it works, just create a blank query, go to Advanced Editor, and replace the text there with the M code below.
Note that M is case sensitive, and this works because the matching words were all UPPERCASE. If that is not the case with your real data, add a step to make everything upper or lower case before the lists and comparisons.
//call this one "Words" let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCknNLchJLElVMFTSUQpwDQr297MO9/d19LMGYqVYHSQVRkAVzo6+rkGO1iFhqFLGYKkQaxd/d6XYWAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Template = _t, Words = _t]), #"Changed Type" = Table.TransformColumnTypes(Source,{{"Template", type text}, {"Words", type text}}), #"Added Custom" = Table.AddColumn(#"Changed Type", "WordList", each Text.Split([Words], ";")), #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Words"}) in #"Removed Columns"//call this one "Text" let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("VczBCsIwEIThVxlyUujFRyhaPDWVevAQegjtlghNVpIF9e1dWhG8/sx8zplL0187i+zTxBFCL8Gta2uLyJn+skZTmdbLGLAbOYm/pwK/LJCQifDkPBXwrOv4WLwQDnszVM6cujPUwbFum75WwzLixkxMBYkFX2/lNmjmrK/3Cgb6oUXN4QM=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Value = _t, Result = _t]), #"Changed Type" = Table.TransformColumnTypes(Source,{{"Value", type text}, {"Result", type text}}), #"Removed Other Columns" = Table.SelectColumns(#"Changed Type",{"Value"}), #"Added Custom1" = Table.AddColumn(#"Removed Other Columns", "TextList", each Text.Split([Value], " ")), #"Added Custom" = Table.AddColumn(#"Added Custom1", "Custom", each Words), #"Expanded Custom" = Table.ExpandTableColumn(#"Added Custom", "Custom", {"Template", "WordList"}, {"Template", "WordList"}), #"Added Custom2" = Table.AddColumn(#"Expanded Custom", "Match", each if List.ContainsAll([TextList], [WordList]) then "Yes" else "No"), #"Removed Other Columns1" = Table.SelectColumns(#"Added Custom2",{"Value", "Template", "Match"}) in #"Removed Other Columns1"If this works for you, please mark it as the solution. Kudos are appreciated too. Please let me know if not.
Regards,
Pat
- 5 years ago
msmays5 - try this. Two tables/queries:
This is called Words, and it looks like this - starts with your initial table above, then I added a column to convert it to lists. You can see what one of the embedded lists looks like:let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCknNLchJLElVMFTSUQpwDQr297MO9/d19LMGYqVYHSQVRkAVzo6+rkGO1iFhqFLGYKkQaxd/d6XYWAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Template = _t, Words = _t]), #"Added Custom" = Table.AddColumn(Source, "WordList", each Text.Split([Words], ";")) in #"Added Custom"Next table is this. It also converts your sentences to a list, then uses List.Generate to cycle through the Words lists (above). A 1 means a match was found in one of the templates, 0 means it wasn't. You can do what you want with the 1/0 records at that point.
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCnANCvb3UyhKzEvJz1UoSa0oUQj393X0U8jNL0pFEQYKKsXqRCu5+LsrAIUVnB19XYMclWJjAQ==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Value = _t]), #"Added Custom" = Table.AddColumn(Source, "AllWords", each Text.Split([Value], " ")), ContainsWords = Table.AddColumn( #"Added Custom", "Contains Words", each let varCurrentWords = [AllWords], varTemplates = Table.RowCount(Words) in Record.Field( Record.Combine( List.Generate( () => [x = 0, y = 0], each [x] < varTemplates, each [ y = if List.ContainsAll(varCurrentWords, Words[WordList]{[x]}) then [y] + 1 else [y], x = [x] + 1 ] ) ), "y") ) in ContainsWordsHow to use M code provided in a blank query:
1) In Power Query, select New Source, then Blank Query
2) On the Home ribbon, select "Advanced Editor" button
3) Remove everything you see, then paste the M code I've given you in that box.
4) Press Done
5) See this article if you need help using this M code in your model. - 5 years ago
Hi, msmays5
First, convert the RequiredWords form to the following lists form
// RequiredWords let Source = Table.FromRecords(Json.Document(Binary.Decompress(Binary.FromText("i65WCknNLchJLElVsoIzFQyVdJTC84tSioGCAa5Bwf5+1uH+vo5+1kCsVKuDXZMRkiZnR1/XIEfrkDCcqo1RVIdYu/i7K9XGAgA=", BinaryEncoding.Base64),Compression.Deflate))), trans = Table.TransformColumns(Source,{"Words", each Text.Split(_,";")}), toRows = Table.ToRows(trans) in toRowsThen Table1's query code is written like this:
// Table1 let Source = Table.FromRecords(Json.Document(Binary.Decompress(Binary.FromText("i65WCkvMKU1VslIKcA0K9vdTKErMS8nPVShJrShRCPf3dfRTyM0vSkURBgoq1eogdLr4uysApRWcHX1dgxxxSIXoQOXB/JAwpdpYAA==", BinaryEncoding.Base64),Compression.Deflate))), result = Table.AddColumn( Source, "Result", (r)=>let match_template = Text.Combine( List.Transform( RequiredWords, each if List.ContainsAll({r[Value]}, _{1}, Text.Contains) then _{0} else null ), ", " ) in if match_template ="" then "No match" else "Match: " & match_template ) in resultThe converted Table1 table is shown below:
msmays5 - try this. Two tables/queries:
This is called Words, and it looks like this - starts with your initial table above, then I added a column to convert it to lists. You can see what one of the embedded lists looks like:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCknNLchJLElVMFTSUQpwDQr297MO9/d19LMGYqVYHSQVRkAVzo6+rkGO1iFhqFLGYKkQaxd/d6XYWAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Template = _t, Words = _t]),
#"Added Custom" = Table.AddColumn(Source, "WordList", each Text.Split([Words], ";"))
in
#"Added Custom"
Next table is this. It also converts your sentences to a list, then uses List.Generate to cycle through the Words lists (above). A 1 means a match was found in one of the templates, 0 means it wasn't. You can do what you want with the 1/0 records at that point.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCnANCvb3UyhKzEvJz1UoSa0oUQj393X0U8jNL0pFEQYKKsXqRCu5+LsrAIUVnB19XYMclWJjAQ==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Value = _t]),
#"Added Custom" = Table.AddColumn(Source, "AllWords", each Text.Split([Value], " ")),
ContainsWords =
Table.AddColumn(
#"Added Custom",
"Contains Words",
each
let
varCurrentWords = [AllWords],
varTemplates = Table.RowCount(Words)
in
Record.Field(
Record.Combine(
List.Generate(
() => [x = 0, y = 0],
each [x] < varTemplates,
each
[
y = if List.ContainsAll(varCurrentWords, Words[WordList]{[x]})
then [y] + 1
else [y],
x = [x] + 1
]
)
),
"y")
)
in
ContainsWords
How to use M code provided in a blank query:
1) In Power Query, select New Source, then Blank Query
2) On the Home ribbon, select "Advanced Editor" button
3) Remove everything you see, then paste the M code I've given you in that box.
4) Press Done
5) See this article if you need help using this M code in your model.
mahoneypat edhans Thank you both for your quick answers! They both worked perfectly (and mahoneypat, extra kudos for returning the template name!)