Forum Discussion
Combining Common value
Hello,
I have a field, which contains several values as below:
| A, B |
| D, E, F |
| A, C |
| B, C |
| D, E, G |
How can I group them together into a common group? Result as below:
| A, B, C |
| D, E, F, G |
| A, B, C |
| A, B, C |
| D, E, F, G |
ImkeF please take a look. I think this has to use a custom loop function, but I dont know how
Hi Iamnvt,
if you have many values on one row, split them into pairs and apply the code for relation pairs as suggested earlier.
This code splits many values on a row into pairs. For example: A,B,C => {{A,B}, {B,C}}
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WctRRcNJRcFaK1YlWAjF0FFx1FNzAXCDbBcxwAQqCGXApXx0FP5hUlFJsLAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Column1 = _t]), Pairs = Table.AddColumn( Source, "Pairs", (row) => let lst =Text.Split(row[Column1], ", "), lstToPairs = List.Accumulate( lst, [lastElement = null, resultList = {}], (state, current) => if state[lastElement] = null then [ lastElement = current, resultList = {} ] else [ lastElement = current, resultList = List.Combine( { state[resultList], { [ First = state[lastElement], Second = current ] } } ) ] ) in lstToPairs ), #"Expanded Pairs" = Table.ExpandRecordColumn(Pairs, "Pairs", {"resultList"}, {"Pairs.resultList"}), #"Expanded Pairs.resultList" = Table.ExpandListColumn(#"Expanded Pairs", "Pairs.resultList"), #"Expanded Pairs.resultList1" = Table.ExpandRecordColumn(#"Expanded Pairs.resultList", "Pairs.resultList", {"First", "Second"}) in #"Expanded Pairs.resultList1"Nolock this gives the expected result!.
Just for further understanding, I am thinking for solution you gave at the first place, if I repeat the code for the "SomethingInCommon" column, it also gives me the result;
How can I make the code recursive with while loop until no further transformation of the value in the row?
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WctRRcNJRcNZRcFGK1YlWArHBDLiIi46CK5jhqqPgphQbCwA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Column1 = _t]), // split text into a list of values TempValueAsList = Table.AddColumn(Source, "TempValueAsList", each Text.Split([Column1], ", ")), // create new a column with all rows' values in common SomethingInCommon = Table.AddColumn( TempValueAsList, "SomethingInCommon", (curRow) => let // get all rows containing any of elements of the current record tableWithSameElements = Table.SelectRows(TempValueAsList, (nestedRow) => List.ContainsAny(curRow[TempValueAsList], nestedRow[TempValueAsList])), // get the column TempValueAsList listToUnion = tableWithSameElements[TempValueAsList], // union and sort all elements resultList = List.Sort(List.Union(listToUnion)), // convert the result list to a text resultAsText = Text.Combine(resultList, ",") in resultAsText ), // remove temp column RemoveTempColumn = Table.RemoveColumns(SomethingInCommon, {"TempValueAsList"}), TempValueAsList2 = Table.AddColumn(RemoveTempColumn, "TempValueAsList2", each Text.Split([SomethingInCommon], ",")), // create new a column with all rows' values in common SomethingInCommon2 = Table.AddColumn( TempValueAsList2, "SomethingInCommon2", (curRow) => let // get all rows containing any of elements of the current record tableWithSameElements = Table.SelectRows(TempValueAsList2, (nestedRow) => List.ContainsAny(curRow[TempValueAsList2], nestedRow[TempValueAsList2])), // get the column TempValueAsList listToUnion = tableWithSameElements[TempValueAsList2], // union and sort all elements resultList = List.Sort(List.Union(listToUnion)), // convert the result list to a text resultAsText = Text.Combine(resultList, ",") in resultAsText ), // remove temp column RemoveTempColumn2 = Table.RemoveColumns(SomethingInCommon2, {"TempValueAsList2"}) in RemoveTempColumn2s
12 Replies
- NolockResident Rockstar
Hi Iamnvt,
I have a solution for you - the code is commented and contains also some sample data. If you have any questions, don't hesitate to ask :)
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WctRRcFKK1YlWctFRcNVRcAOzgYLOYIYTjAGRdVeKjQUA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Column1 = _t]), // split text into a list of values TempValueAsList = Table.AddColumn(Source, "TempValueAsList", each Text.Split([Column1], ", ")), // create new a column with all rows' values in common SomethingInCommon = Table.AddColumn( TempValueAsList, "SomethingInCommon", (curRow) => let // get all rows containing any of elements of the current record tableWithSameElements = Table.SelectRows(TempValueAsList, (nestedRow) => List.ContainsAny(curRow[TempValueAsList], nestedRow[TempValueAsList])), // get the column TempValueAsList listToUnion = tableWithSameElements[TempValueAsList], // union and sort all elements resultList = List.Sort(List.Union(listToUnion)), // convert the result list to a text resultAsText = Text.Combine(resultList, ",") in resultAsText ), // remove temp column RemoveTempColumn = Table.RemoveColumns(SomethingInCommon, {"TempValueAsList"}) in RemoveTempColumnAnd a screenshot of the result.
- IamnvtContinued Contributor
Nolock absolutely brilliant!
I have a bit more complex scenarios:
Column1SomethingInCommon
A, B A,B,C,D,E,F B, C A,B,C,D,E,F C, D A,B,C,D,E,F D, E A,B,C,D,E,F E, F A,B,C,D,E,F it has a bridge between A,B and B,C and C, D --> B,C is the bridge --> result should be A,B,C,D
How can I achieve that?
Thank you very much for the above solution; it already helped me a lot.