某游戏的角色强弱由武力,统率,智力,敏捷和运气这五个指标决定。该游戏会出现十三个特殊情景,每当进入这些情景玩家就会面临多个选择并需要从中挑选一个出来。根据游戏的攻略,每一个选项都会对某角色的武力,统率,智力,敏捷和运气产生不同程度的影响,具体的数据如下图所示:

现要求计算出每一个组合的路径图以及对五围的累计影响,如下图所示:

从直觉出发,这个问题应该使用Table.AddColumn()或者List.TransformMany()产生笛卡尔积进行解答。遗憾的是, 即使只有十三个情景, 采用这种思路进行解题的运行时间会长得令人难以接受。因此,有必要从另一个角度理解这个问题:从游戏的角度出发,每一个情景的出现实际上是有先后的次序。如果我们把先后的次序理解为一种从属的关系(比如:情景二从属于情景一,情景三从属于情景二,如此类推),不难发现应该借鉴BOM树形结构分解(详情请查阅施阳老师同标题的文章)的思路进行解题。为了方便进行分步解释,问题会暂时化简为只有两个特殊情景,并为了与最终答案保持一致,会保留一些多余的步骤。第一步,需要定义如下常数串列:
Constant_List =
{
"武力",
"统率",
"智力",
"敏捷",
"运气"
}
第二步,需要把武力,统率,智力,敏捷和运气这五列通过Table.CombineColumnsToRecord()转化为内嵌的记录:
Columns_To_Record =
Table.CombineColumnsToRecord(
Dataset,
"nList",
Constant_List
)

第三步,需要通过Table.TransformColumns()把内嵌的记录转化为内嵌的复合串列:
Record_To_nList =
Table.TransformColumns(
Columns_To_Record,
{
"nList",
each {Record.ToList(_)},
type list
}
)

第四步,把情景一的选择分离出来并更改部分列名:
fScenario =
Table.RenameColumns(
Table.SelectRows(
Record_To_nList,
each [情景] = 1
),
{
{
"选项",
"路径"
},
{
"nList",
"五围"
}
}
)

第五步,把其他情景的选项分离出来:
oScenario =
Table.SelectRows(
Record_To_nList,
each [情景] ˃ 1
)

第六步,通过Table.AddColumn()为大于1的情景计算出上一情景:
Previous_Scenarios =
Table.AddColumn(
oScenario,
"上一情景",
each [情景] - 1,
Int64.Type
)

第七步,以内连接把第六步所得的表格与第四步所得的表格连接起来, 匹配的行会以表格的形式内嵌于nTable列:
InnerJoin =
Table.NestedJoin(
Previous_Scenarios,
"上一情景",
fScenario,
"情景",
"nTable",
JoinKind.Inner
)

第八步,展开nTable列中的部分列并为这些列更改名字:
Expansion =
Table.ExpandTableColumn(
InnerJoin,
"nTable",
{
"路径",
"五围"
},
{
"上一路径",
"上一五围"
}
)

第九步,计算路径图:
Add_Path =
Table.AddColumn(
Expansion,
"路径",
each
Text.Combine(
{
[上一路径],
[选项]
},
"|"
),
type text
)

第十步,通过List.Combine()组合当前的五围数据与之前的五围数据:
Add_Summation =
Table.AddColumn(
Add_Path,
"五围",
each
List.Combine(
{
[上一五围],
[nList]
}
),
type list
)

第十一步,通过Table.SelectColumn()移除情景,路径和五围之外的列。
RemoveCols =
Table.SelectColumns(
Add_Summation,
{
"情景",
"路径",
"五围"
}
)

第十二步,利用List.Zip()实现行列转换后计算对五围的累计影响并转化结果为内嵌的记录:
TransCol =
Table.TransformColumns(
RemoveCols,
{
"五围",
(x)=˃
Record.FromList(
List.Transform(
List.Zip(
x
),
(y)=˃ List.Sum(y)
),
Constant_List
),
type record
}
)

第十三步,展开内嵌记录中的所有字段:
Expand_Records =
Table.ExpandRecordColumn(
TransCol,
"五围",
Constant_List
)

第十四步,移除情景列:
RemoveCol =
Table.RemoveColumns(
Expand_Records,
"情景"
)

第十五步,修改新列的数据类型:
DataType =
Table.TransformColumnTypes(
RemoveCol,
List.Zip(
{
Constant_List,
List.Repeat(
{Int64.Type},
List.Count(Constant_List)
)
}
)
)

回到原来十三个情景的问题上,只需要利用List.Accumulate()重复以上的第七到第十一步就可以完成解答,完整代码如下:
let
Constant_List =
{
"武力",
"统率",
"智力",
"敏捷",
"运气"
},
Columns_To_Record =
Table.CombineColumnsToRecord(
Dataset,
"nList",
Constant_List
),
Record_To_nList =
Table.TransformColumns(
Columns_To_Record,
{
"nList",
each {Record.ToList(_)},
type list
}
),
fScenario =
Table.RenameColumns(
Table.SelectRows(
Record_To_nList,
each [情景] = 1
),
{
{
"选项",
"路径"
},
{
"nList",
"五围"
}
}
),
oScenario =
Table.SelectRows(
Record_To_nList,
each [情景] ˃ 1
),
Previous_Scenarios =
Table.AddColumn(
oScenario,
"上一情景",
each [情景] - 1,
Int64.Type
),
Grouping =
Table.Group(
Previous_Scenarios,
"情景",
{
"nTable",
each _,
type table
[
情景 = Int64.Type,
选项 = text,
nList = list,
上一情景 = Int64.Type
]
}
),
Acc_Process =
List.Accumulate(
Table.Column(
Grouping,
"nTable"
),
fScenario,
(x, y)=˃
let
InnerJoin =
Table.NestedJoin(
y,
"上一情景",
x,
"情景",
"nTable",
JoinKind.Inner
),
Expansion =
Table.ExpandTableColumn(
InnerJoin,
"nTable",
{
"路径",
"五围"
},
{
"上一路径",
"上一五围"
}
),
Add_Path =
Table.AddColumn(
Expansion,
"路径",
each
Text.Combine(
{
[上一路径],
[选项]
},
"|"
),
type text
),
Add_Summation =
Table.AddColumn(
Add_Path,
"五围",
each
List.Combine(
{
[上一五围],
[nList]
}
),
type list
),
RemoveCols =
Table.SelectColumns(
Add_Summation,
{
"情景",
"路径",
"五围"
}
)
in
RemoveCols
),
TransCol =
Table.TransformColumns(
Acc_Process,
{
"五围",
(x)=˃
Record.FromList(
List.Transform(
List.Zip(
x
),
(y)=˃ List.Sum(y)
),
Constant_List
),
type record
}
),
Expand_Records =
Table.ExpandRecordColumn(
TransCol,
"五围",
Constant_List
),
RemoveCol =
Table.RemoveColumns(
Expand_Records,
"情景"
),
DataType =
Table.TransformColumnTypes(
RemoveCol,
List.Zip(
{
Constant_List,
List.Repeat(
{Int64.Type},
List.Count(Constant_List)
)
}
)
)
in
DataType
玩到一半我发现攻略里提到如果想让角色得到完美的培养,最后五个选项必须为2,2,1,1,1,并且武力和运气要大于等于50,而统率要大于等于40。对计算出的结果进行筛选,发现要实现完美培养只有一种组合根本没有容错的空间,所以只能开新档重玩了

歪楼问个很基础的问题 合并excel文档查询怎么添加一列 让这一列显示的是这个excel文件的名称呢?(举个例子下载了三个产品的数据指标,每个产品对应的excel文件只能通过文件名判断这是那个产品,但是里面内容没有产品标识,在利用excel的合并查询时,如何添加一列,使得每个产品数据文档前面增加一列作为产品名称,这个产品名称就是产品excel文件的名称)似乎表述的不太清晰
不知道你需要的是不是这种效果:
let
Source = Folder.Files("D:\OneDrive\PQ Fans\Reply\Reply 1\Data Folder"),
Trans_Col =
Table.TransformColumns(
Source,
{
{
"Content",
(x)=>
Table.SelectRows(
Excel.Workbook(
x,
true
),
(y)=> y[Name] = "Tbl"
){0}[Data]
},
{
"Name",
each Text.Split(_, "."){0},
type text
}
}
),
Col_Selection =
Table.SelectColumns(
Trans_Col,
{
"Content",
"Name"
}
),
Expansion =
Table.ExpandTableColumn(
Col_Selection,
"Content",
{
"No"
}
)
in
Expansion