Extract the last group of alphabets followed by numbers in each Text and concat them with a dash in between for each Set. Maintain original count of text and new count of text joined. Ex. U67G3QR – Last group is G3. 6736 – There is no alphabet followed by numbers here. PQR – There is no alphabet followed by numbers here.
📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 184
Challenge Difficulty: ⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn
Solving the challenge of Extract Ending Pattern Group with Power Query
Power Query solution 1 for Extract Ending Pattern Group, proposed by Zoran Milokanović:
let
Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content],
A = {"a" .. "z", "A" .. "Z"},
N = {"0" .. "9"},
C = (_, X) => Text.Length(Text.Select(_, X)) > 0,
G = Table.Group(
Table.AddColumn(
Source,
"T",
each List.Last(
List.Select(
Splitter.SplitTextByCharacterTransition(N, A)([Text]),
each List.AllTrue({C(_, A), C(_, N)})
)
)
),
{"Set"},
{
{"Text", each Text.Combine([T], "-")},
{"Original Count", each List.Count([T])},
{"New Count", each List.NonNullCount([T])}
}
)
in
G
Power Query solution 2 for Extract Ending Pattern Group, proposed by Aditya Kumar Darak 🇮🇳:
let
Source = Excel.CurrentWorkbook(){[Name = "data"]}[Content],
Digits = {"0" .. "9"},
Alphabets = {"A" .. "Z", "a" .. "z"},
Transform = Table.TransformColumns(
Source,
{
"Text",
each [
S = Splitter.SplitTextByCharacterTransition(Digits, Alphabets)(_),
L = List.Select(
S,
(f) =>
[
t = List.Transform({Digits, Alphabets}, (x) => Text.Length(Text.Select(f, x))),
r = List.Min(t) <> 0
][r]
),
R = List.Last(L)
][R]
}
),
Return = Table.Group(
Transform,
"Set",
{
{"Text", each Text.Combine([Text], "-")},
{"Old Count", Table.RowCount},
{"New Count", each List.NonNullCount([Text])}
}
)
in
Return
Power Query solution 3 for Extract Ending Pattern Group, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Group = Table.Group(
Source,
{"Set"},
{
{
"A",
each
let
a = [Text],
b = List.RemoveNulls(
List.Transform(
a,
each
let
c = Splitter.SplitTextByCharacterTransition({"0" .. "9"}, {"A" .. "z"})(_),
d = List.Last(
List.Select(
c,
each try
not List.Contains({"0" .. "9"}, Text.Start(_, 1))
and Number.From(Text.End(_, 1))
is number
otherwise
false
)
)
in
d
)
),
e = Text.Combine(b, "-"),
f = List.Count([Text]),
g = List.Count(b),
h = Table.FromColumns({{e}, {f}, {g}}, {"Text", "Original Count", "New Count"})
in
h
}
}
),
Sol = Table.ExpandTableColumn(Group, "A", Table.ColumnNames(Group[A]{0}))
in
Sol
Power Query solution 4 for Extract Ending Pattern Group, proposed by Luan Rodrigues:
let
Fonte = Tabela1,
add = Table.AddColumn(
Fonte,
"Personalizar",
each [
a = Splitter.SplitTextByCharacterTransition({"0" .. "9"}, {"A" .. "Z", "a" .. "z"})([Text]),
b = List.Select(a, each List.ContainsAny(Text.ToList(_), {"0" .. "9"})),
c = List.Last(List.Select(b, each List.ContainsAny(Text.ToList(_), {"A" .. "Z", "a" .. "z"})))
][c]
),
gp = Table.Group(
add,
{"Set"},
{
{
"Contagem",
each
let
a = Text.Combine([Personalizar], "-"),
b = List.Count([Text]),
c = List.Count(List.RemoveNulls([Personalizar]))
in
Table.FromRows({{a, b, c}}, {"Text", "Original Count", "New Count"})
}
}
),
res = Table.ExpandTableColumn(gp, "Contagem", Table.ColumnNames(gp[Contagem]{0}))
in
res
Power Query solution 5 for Extract Ending Pattern Group, proposed by Brian Julius:
let
Source = DataRaw,
RScript = R.Execute(
"library(stringr)#(lf)df <- dataset#(lf)target <- ""([A-Za-z]+)(d+)(?!.*[A-Za-z]+d+)""#(lf)df$Cleaned <- sapply(str_extract_all(df$Text, target ), function(x) paste(x, collapse = "", ""))#(lf)df",
[dataset = Source]
),
Result = RScript{[Name = "df"]}[Value],
RepBlanks = Table.ReplaceValue(Result, "", null, Replacer.ReplaceValue, {"Cleaned"}),
Group = Table.Group(
RepBlanks,
{"Set"},
{
{"OrigCount", each List.Count(_)},
{"NewCount", each List.Count(List.Select(_, each [Cleaned] <> null))},
{"Text", each [Cleaned]}
}
),
Extract = Table.TransformColumns(
Group,
{"Text", each Text.Combine(List.Transform(_, Text.From), "-")}
),
Reorder = Table.ReorderColumns(Extract, {"Set", "Text", "OrigCount", "NewCount"})
in
Reorder
Power Query solution 6 for Extract Ending Pattern Group, proposed by Ramiro Ayala Chávez:
let
S = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
a = Table.TransformColumnTypes(S, {"Text", type text}),
b = Table.Group(a, {"Set"}, {{"Original Count", each Table.RowCount(_)}, {"T", each [Text]}}),
Fx = (x) =>
let
T = List.Transform,
A = x,
B = T(A, Splitter.SplitTextByCharacterTransition({"0" .. "9"}, {"A" .. "z"})),
C = T(B, each T(_, each Text.ToList(_))),
D = T(C, each T(_, each if List.ContainsAny(_, {"0" .. "9"}) then _ else {null})),
E = T(D, each T(_, each if List.ContainsAny(_, {"A" .. "z"}) then Text.Combine(_) else null)),
F = List.RemoveNulls(T(E, each List.Last(List.RemoveNulls(_)))),
G = Text.Combine(F, "-")
in
G,
c = Table.AddColumn(b, "Text", each Fx([T])),
d = Table.AddColumn(c, "New Count", each List.Count(Text.Split([Text], "-"))),
Sol = Table.SelectColumns(d, {"Set", "Text", "Original Count", "New Count"})
in
Sol
Power Query solution 7 for Extract Ending Pattern Group, proposed by Eric Laforce:
let
Source = Excel.CurrentWorkbook(){[Name = "tData184"]}[Content],
NChar = {"0" .. "9"},
LChar = {"A" .. "Z", "a" .. "z"},
Group = Table.Group(
Source,
"Set",
{
{
"Text",
each
let
_L = List.Transform(
[Text],
each
let
_Split = Splitter.SplitTextByCharacterTransition(NChar, LChar)(_),
_Select = List.Select(
_Split,
each List.Contains(LChar, Text.Start(_, 1))
and List.Contains(NChar, Text.End(_, 1))
)
in
List.Last(_Select)
)
in
Text.Combine(_L, "-")
},
{"Original Count", List.Count}
}
),
Add_NewC = Table.AddColumn(Group, "New Count", each List.Count(Text.Split([Text], "-")))
in
Add_NewC
Power Query solution 8 for Extract Ending Pattern Group, proposed by 🇮🇷 Navid Esmaeilzadeh اسماعیل زاده:
let
S = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
A = Table.AddColumn(
S,
"Sp",
each Splitter.SplitTextByCharacterTransition({"0" .. "9"}, {"A" .. "Z", "a" .. "z"})([Text])
),
B = Table.ExpandListColumn(A, "Sp"),
C = Table.AddColumn(
B,
"L",
each
let
A = Text.Length(Text.Select([Sp], {"A" .. "Z", "a" .. "z"})),
B = Text.Length(Text.Select([Sp], {"0" .. "9"})),
C = Text.Length([Sp]),
D = C - A,
E = C - B,
F = if D = 0 or E = 0 then null else true
in
F
),
D = Table.SelectRows(C, each ([L] = true)),
E = Table.Group(
D,
{"Set", "Text"},
{{"Tbl", each _, type table [Set = text, Text = text, Sp = text, L = logical]}}
),
F = Table.AddColumn(E, "Lp", each List.Last([Tbl][Sp])),
G = Table.Group(F, {"Set"}, {{"txt", each Text.Combine([Lp], "-"), type text}}),
H = Table.AddColumn(G, "Org-C", each Table.RowCount(Table.SelectRows(S, (OC) => OC[Set] = [Set]))),
I = Table.AddColumn(H, "N-C", each Table.RowCount(Table.SelectRows(F, (NC) => NC[Set] = [Set])))
in
I
Power Query solution 9 for Extract Ending Pattern Group, proposed by Venkata Rajesh:
let
Source = Data,
Text = Table.AddColumn(
Source,
"NewText",
each [
x = Splitter.SplitTextByCharacterTransition({"0" .. "9"}, {"a" .. "z", "A" .. "Z"})([Text]),
y = List.Select(
x,
each [
x = Text.Select(Text.Upper(_), {"A" .. "Z"}),
y = Text.Select(_, {"0" .. "9"}),
z = Text.Length(x) > 0 and Text.Length(y) > 0
][z]
),
z = List.Last(y)
][z]
),
Group = Table.Group(
Text,
{"Set"},
{
{"Text", each Text.Combine(List.RemoveNulls([NewText]), "-"), Text.Type},
{"Original Count", each Table.RowCount(_), Int64.Type},
{"New Count", each List.NonNullCount([NewText]), Int64.Type}
}
)
in
Group
Solving the challenge of Extract Ending Pattern Group with Excel
Excel solution 1 for Extract Ending Pattern Group, proposed by Bo Rydobon 🇹🇭:
=VSTACK(D1:G1,DROP(GROUPBY(A2:A10,IFNA(REGEXEXTRACT(B2:B10,"[A-Z]+d+(?!.*[A-Z]+d+)",,1),""),
HSTACK(LAMBDA(x,TEXTJOIN("-",,x)),ROWS,LAMBDA(x,SUM(--(x>"")))),,0),1))
=REGEXEXTRACT(B2:B10,"[A-Za-z]+d+(?![A-Za-z]+d+)")
Explanation for learning
[A-Za-z]+d+ capture Alphabet+ follow by digit+
?! Exclude anything follow by Negative Lookahead
(?![A-Za-z]+d+) Exclude anything follow by Alphabet+follow by digit+
[A-Za-z]+d+(?![A-Za-z]+d+)
Excel solution 2 for Extract Ending Pattern Group, proposed by Bo Rydobon 🇹🇭:
=REDUCE(D1:G1,UNIQUE(A2:A10),LAMBDA(a,v,
LET(y,A2:A10=v,m,MAP(0&IF(y,B2:B10),LAMBDA(b,LET(s,SEQUENCE(26),c,TAKE(TEXTSPLIT(b,,CHAR(s+64),1,1),-1),IFERROR(TEXTAFTER(TEXTBEFORE(b,c,-1),s-1,-1)&c,"")))),VSTACK(a,HSTACK(v,TEXTJOIN("-",,m),SUM(N(m>"")),SUM(--y))))))
Excel solution 3 for Extract Ending Pattern Group, proposed by محمد حلمي:
=LET(s,A2:A10,d,SEQUENCE(26)-1,
x,MAP(B2:B10,LAMBDA(b,LET(
j,TEXTSPLIT(b,d,,1)&TEXTSPLIT(b,CHAR(d+65),,1,1),
XLOOKUP(9,FIND(j,b),j,"",-1)))),
REDUCE(D1:G1,UNIQUE(s),LAMBDA(a,v,LET(
e,REPT(x,s=v),VSTACK(a,
HSTACK(v,TEXTJOIN("-",,e),COUNTIF(s,v),SUM(N(e>""))))))))
Excel solution 4 for Extract Ending Pattern Group, proposed by محمد حلمي:
=REDUCE(D1:G1,UNIQUE(A2:A10),LAMBDA(a,v,VSTACK(a,LET(s,A2:A10,d,SEQUENCE(26),e,REPT(MAP(B2:B10,LAMBDA(
b,LET(j,TEXTSPLIT(b,d-1,,1)&TEXTSPLIT(b,CHAR(d+64),,1,1),
XLOOKUP(9,FIND(j,b),j,"",-1)))),s=v),
HSTACK(v,TEXTJOIN("-",,e),COUNTIF(s,v),SUM(N(e>"")))))))
Excel solution 5 for Extract Ending Pattern Group, proposed by محمد حلمي:
=REDUCE(D1:G1,UNIQUE(A2:A10),LAMBDA(a,v,VSTACK(a,LET(s,A2:A10,e,REPT(MAP(B2:B10,LAMBDA(b,LET(d,SEQUENCE(26),j,TEXTSPLIT(b,d-1,,1)&TEXTSPLIT(b,CHAR(d+64),,1,1),
IFNA(LOOKUP(9,FIND(j,b),j),)))),s=v),
HSTACK(v,TEXTJOIN("-",,e),COUNTIF(s,v),SUM(N(e>"")))))))
Excel solution 6 for Extract Ending Pattern Group, proposed by محمد حلمي:
=REDUCE(D1:G1,UNIQUE(A2:A10),LAMBDA(a,v,VSTACK(a,LET(s,A2:A10,e,REPT(MAP(B2:B10,LAMBDA(b,LET(d,SEQUENCE(26),j,TEXTSPLIT(b,d-1,,1)&TEXTSPLIT(b,CHAR(d+64),,1,1),
i,IFERROR(IF(FIND(j,b),j),),XLOOKUP(TRUE,i>0,i,"",,-1)))),s=v),
HSTACK(v,TEXTJOIN("-",,e),COUNTIF(s,v),SUM(N(e>"")))))))
Excel solution 7 for Extract Ending Pattern Group, proposed by Julian Poeltl:
=LET(T,A1:B10,TT,DROP(T,1),S,TAKE(TT,,1),Te,TAKE(TT,,-1),US,UNIQUE(S),OC,MAP(US,LAMBDA(A,COUNTA(FILTER(S,S=A)))),TC,MAP(Te,LAMBDA(A,LET(L,LEN(A),SL,SEQUENCE(L),SP,MID(A,SEQUENCE(L),1),PN,ISNUMBER(SP*1)*SL,PT,ISNUMBER(XMATCH(UPPER(SP),CHAR(64+SEQUENCE(26))))*SL,MN,MAX(PN),MT,MAX(FILTER(PT,PT
Excel solution 8 for Extract Ending Pattern Group, proposed by Duy Tùng:
=DROP(GROUPBY(A2:A10,MAP(B2:B10,LAMBDA(x,IFNA(TAKE(REGEXEXTRACT(x,"[a-zA-Z]+d+",1),,-1),""))),HSTACK(LAMBDA(x,TEXTJOIN("-",,x)),COUNTA,LAMBDA(v,SUM(N(v>"")))),,0),1)
Excel solution 9 for Extract Ending Pattern Group, proposed by Sunny Baggu:
=DROP(
REDUCE(
"",
UNIQUE(A2:A10),
LAMBDA(x, y,
VSTACK(
x,
LET(
_f, FILTER(B2:B10, A2:A10 = y),
_c, DROP(
REDUCE(
"",
_f,
LAMBDA(a, v,
VSTACK(
a,
LET(
_a, TEXTSPLIT(v, , SEQUENCE(10) - 1, 1),
_b, TEXTSPLIT(v, , _a, 1),
_r, MIN(ROWS(_a), ROWS(_b)),
_a1, IF(_r = 1, TAKE(_a, 1), TAKE(_a, -1)),
_b1, IF(_r = 1, TAKE(_b, -1), TAKE(_b, -1)),
IFERROR(_a1 & _b1, "")
) )
) ),
1
),
_c1, FILTER(_c, _c <> ""),
HSTACK(y, TEXTJOIN("-", , _c1), ROWS(_f), ROWS(_c1))
) ) ) ), 1)
Excel solution 10 for Extract Ending Pattern Group, proposed by 🇵🇪 Ned Navarrete C.:
=LET(e,MAP(B2:B10,LAMBDA(i,LET(c,TEXTSPLIT(i,CHAR(ROW(65:90)),,1,1),t,TAKE(c,,-1),IFERROR(TAKE(TEXTSPLIT(TEXTBEFORE(i,t),ROW(1:10)-1,,1),,-1)&t,"")))),REDUCE(D1:G1,UNIQUE(A2:A10),LAMBDA(a,v,LET(f,FILTER(e,A2:A10=v),VSTACK(a,HSTACK(v,TEXTJOIN("-",1,f),ROWS(f),SUM(N(f>""))))))))
Excel solution 11 for Extract Ending Pattern Group, proposed by Md. Zohurul Islam:
=LET(u,A2:A10,v,B2:B10,
sq,CHAR(SEQUENCE(26,,65)),
num,SEQUENCE(10,,0),
hdr,HSTACK(A1:B1,"Original Count","New Count"),
w,MAP(v,LAMBDA(x,LET(a,TEXTSPLIT(x,sq,,1,1),
b,TAKE(a,,-1),
c,TEXTBEFORE(x,b),
d,TEXTSPLIT(c,num,,1),
e,TAKE(d,,-1),
f,IFERROR(e&b,""),
f))),
z,REDUCE(hdr,UNIQUE(u),LAMBDA(x,y,LET(
g,FILTER(w,u=y),
h,TEXTJOIN("-",1,g),
I,COUNTA(g),
j,SUM(ABS(g<>"")),
k,HSTACK(y,h,I,j),
m,VSTACK(x,k),m))),
z)
Excel solution 12 for Extract Ending Pattern Group, proposed by LUIS FLORENTINO COUTO CORTEGOSO:
=LET(f,LAMBDA(z,LET(n,TEXTSP&LIT(z,CHAR(ROW(65:91)),,1,1),t,TEXTSPLIT(z,SEQUENCE(10)-1,,1),IFERROR(CONCAT(CHOOSECOLS(t,-2),TAKE(n,,-1)),""))),VSTACK(D1:G1,DROP(GROUPBY(A2:A10,MAP(0&B2:B10&"a",f),HSTACK(LAMBDA(x,TEXTJOIN("-",1,x)),COUNTA,LAMBDA(x,SUM(--(x>"")))),,0),1) ))
Solving the challenge of Extract Ending Pattern Group with Python
Python solution 1 for Extract Ending Pattern Group, proposed by Konrad Gryczan, PhD:
import pandas as pd
import re
input = pd.read_excel("PQ_Challenge_184.xlsx", usecols="A:B", nrows = 9)
test = pd.read_excel("PQ_Challenge_184.xlsx", usecols="D:G", nrows = 3)
test.columns = test.columns.str.replace(".1", "")
input["group"] = input["Text"].str.findall("[A-Za-z]+\d+")
input["group"] = input["group"].apply(lambda x: x[-1] if len(x) > 1 else x[0] if len(x) == 1 else None)
result = input.groupby("Set").agg(
Text=("group", lambda x: "-".join([group for group in x if group])),
Original_Count=("group", "size"),
New_Count=("group", lambda x: x.notnull().sum())).rename(columns={"Original_Count": "Original Count",
"New_Count": "New Count"}).reset_index()
print(result.equals(test)) # True
Python solution 2 for Extract Ending Pattern Group, proposed by Luan Rodrigues:
PY Solution!
import pandas as pd
import re
import numpy as np
file = r'C:UsersLuanProjetos_PYPYPQ_Challenge_184PQ_Challenge_184.xlsx'
dfc = pd.read_excel(file, usecols="A:B")
df = pd.read_excel(file, usecols="A:B")
df['max'] = df['Text'].apply(lambda x: re.sub(r'(?<=[0-9])(?=[A-Za-z])', ' ', x).split())
df = df[['Set', 'Text', 'max']].explode('max')
df = df[df['max'].apply(lambda x: any(char.isalpha() for char in x) and any(char.isdigit() for char in x))]
dfgroup = df.groupby(['Set', 'Text']).agg({'max': list}).reset_index()
dfgroup['count'] = dfgroup['max'].apply(len)
dfgroup['cond'] = np.where(dfgroup['count'] == 2, dfgroup['max'].str[1], dfgroup['max'].str[0])
def gp(group):
Texto = '-'.join(group['cond'])
return Texto
dfgroup3 = dfgroup.groupby('Set', group_keys=False).apply(gp, include_groups=False).reset_index(name='Text')
dfgroup0 = dfc.groupby('Set').size().reset_index(name='Original Count')
dfgroup1 = dfgroup.groupby('Set').size().reset_index(name='New Count')
df_res = dfgroup3.merge(dfgroup0, on='Set', how='left')
df_res1 = df_res.merge(dfgroup1, on='Set', how='left')
df_res1.columns = ['Set', 'Text', 'Original Count', 'New Count']
print(df_res1)
Solving the challenge of Extract Ending Pattern Group with Python in Excel
Python in Excel solution 1 for Extract Ending Pattern Group, proposed by Abdallah Ally:
# I love regular expressions
import pandas as pd
import re
file_path = 'PQ_Challenge_184.xlsx'
df = pd.read_excel(file_path, usecols='A:B')
# Perform data wrangling
def extract_alphabets(text):
text = re.findall('[a-zA-Z]+d+', text)
return text[-1] if text else ''
df['Alphabets'] = df.iloc[:, 1].map(extract_alphabets)
df = df.groupby('Set').agg(
Text = ('Alphabets', lambda x: '-'.join(x[x != ''])),
Original_Count = ('Set', 'count'),
New_Count = ('Alphabets', lambda x: x[x != ''].count())
).reset_index()
df = df.rename(columns={'Original_Count': 'Original Count',
'New_Count': 'New Count'})
df
Solving the challenge of Extract Ending Pattern Group with R
R solution 1 for Extract Ending Pattern Group, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
input = read_excel("Power Query/PQ_Challenge_184.xlsx", range = "A1:B10")
test = read_excel("Power Query/PQ_Challenge_184.xlsx", range = "D1:G4")
result = input %>%
mutate(group = str_extract_all(Text,"[A-Za-z]+\d+")) %>%
mutate(group = map_chr(group, ~if(length(.x) > 1) tail(.x, 1) else if(length(.x) == 0) NA_character_ else .x)) %>%
summarise(
Text = paste(group[!is.na(group)], collapse = "-"),
`Original Count` = n() %>% as.numeric(),
`New Count` = sum(!is.na(group)) %>% as.numeric(),
.by = Set
)
identical(result, test)
# [1] TRUE
&&
