Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.
The following function converts a number from a certain
base (<16) in the corresponding base 10 value.
I would like to test to possibly improve the management of particular cases that I have not considered.
#########edited################
let
fnBase2Dec = (input, base) =>
let
values = [
0=0,
1=1,
2=2,
3=3,
4=4,
5=5,
6=6,
7=7,
8=8,
9=9,
A=10,
B=11,
C=12,
D=13,
E=14,
F=15
],
digits=Text.ToList(Text.Upper (input)),
dim=List.Count(digits)-1,
exp=if base=null then 16 else base,
fields=Record.FieldNames(values),
values_base=Record.SelectFields(values, List.FirstN(fields, exp)),
Result = List.Sum(List.Transform({0..dim}, each Record.Field(values_base,digits{_})*Number.Power(exp,dim - _)))
in
Result
in
fnBase2Dec
Alright, I like this
Ideas:
1) you should set base as optional:
(input as anynonnull, optional base as number) =>
2) You could add an extra step to transform the input to text in case it's a number (case base2 to base9):
digits = Text.ToList(Text.Upper(Text.From(input))),
3) you could stop it if it's base0 or 1:
exp=if base=null then 16 else base,
Result = if exp < 2 or exp >16 then Error.Record("Base not accepted", "Base given: " & Text.From(exp))
else let
digits=Text.ToList(Text.Upper (input)),
dim=List.Count(digits)-1,
fields=Record.FieldNames(values),
values_base=Record.SelectFields(values, List.FirstN(fields, exp)
in List.Sum(List.Transform({0..dim}, each Record.Field(values_base,digits{_})*Number.Power(exp,dim - _)))
in
Result
4) you could actually not do 3 and change the function's type with Documentation.AllowedValues:
let
fn = .....
, fnType =Type.FroFunction([ReturnType = type any,
Parameters = [input = type anynonnull,
base = type number meta [Documentation.AllowedValues = {2..16}]]],1),
Replace = Value.ReplaceType(fn, fnType)
in Replace
5) You could fix the error message in case an out of bounds character came about:
NumberBase10 = try List.Sum....
Result = if NumberBase10[HasError] then Error.Record("Out of bounds Input", "Character: """ & Text.BetweenDelimiters(NumberBase10[Error][Message], "field '","' of the recor") & """ does not exist in base " & Text.From(exp), input) else NumberBase10[Value]
6) You could dynamically make the transformlist:
values = let
l = if exp < 11 then {"0"..Text.From(exp-1)} else List.Union({{"0".."9"}, List.FirstN({"A".."Z"}, exp-10)})
in Record.FromList({0..List.Count(l)-1}, l),
7) You could use List.Accumulate with List.Zip for no apparent reason:
List.Accumulate(List.Zip({digits, {0..dim}}), 0, (s, x) => s + Record.Field(values_base, x{0})*Number.Power(exp, dim - x{1}))
I think that's all I can think of.
Cheers
Hi Mauro, ok for points 1), 2) and 3). Very well, for point 4) (say 3-bis)) and 5 I understand the spirit, but I have to study the syntax carefully. For point 6) it is not clear to me in which cases it is more flexible than the expressions that manage the bases <16. The 7) very nice, I like it, but even here I have the doubt if it is preferable to the list.transform which seems clearer to me and is perhaps more efficient because it is simpler.
@Anonymous , refer if these two can help
I like this solution (very synthetic) but it is limited to base 16 only
the other seem to me a little redundant.
Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City
Check out the April 2024 Power BI update to learn about new features.
User | Count |
---|---|
99 | |
50 | |
19 | |
12 | |
11 |