let
//Read in table and set data type
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"List", Int64.Type}}),
//Add two more columns where the rows of each column = the full original table
#"Added Custom" = Table.AddColumn(#"Changed Type", "Custom", each #"Changed Type"),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Custom.1", each #"Changed Type"),
//Expand each of the two custom columns
#"Expanded Custom" = Table.ExpandTableColumn(#"Added Custom1", "Custom", {"List"}, {"Custom.List"}),
#"Expanded Custom.1" = Table.ExpandTableColumn(#"Expanded Custom", "Custom.1", {"List"}, {"Custom.1.List"}),
//Add a column which contains a Sorted List of the three data columns
#"Added Custom2" = Table.AddColumn(#"Expanded Custom.1", "Sorted Row", each List.Sort({[List],[Custom.List],[Custom.1.List]})),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom2",{"List", "Custom.List", "Custom.1.List"}),
//Remove the duplicates in the list => 56 items
#"Removed Duplicates" = Table.Distinct(#"Removed Columns"),
//expand the list into a delimited list
#"Added Custom3" = Table.AddColumn(#"Removed Duplicates", "Custom",
each Text.Combine(List.Transform([Sorted Row],each Text.From(_)),"~"), type text),
#"Removed Columns1" = Table.RemoveColumns(#"Added Custom3",{"Sorted Row"}),
//split the column by the delimiter
#"Split Column by Delimiter" = Table.SplitColumn(#"Removed Columns1", "Custom",
Splitter.SplitTextByDelimiter("~", QuoteStyle.Csv), {"Custom.1", "Custom.2", "Custom.3"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{
{"Custom.1", Int64.Type}, {"Custom.2", Int64.Type}, {"Custom.3", Int64.Type}})
in
#"Changed Type1"
对于从一组8个项目中选择7个项目,排列数超过2,000,000,Excel Power Query无法有效处理,因此需要一段时间才能运行。*
在Power BI Desktop上运行的相同代码只需一两秒 *
我将其编写为名为fnCombos的自定义函数
自定义函数
重命名fnCombos*
(l as list, num as number)=>
let
t = Table.FromColumns({l}),
#"Permutations" = List.Last(
List.Generate(
()=>[T=t, idx=0],
each [idx] < num,
each [T = Table.AddColumn([T],Text.From([idx]), each l), idx=[idx]+1],
each [T])),
#"Expand Columns" = List.Accumulate({"0"..Text.From(num-2)},#"Permutations", (state, current)=>
Table.ExpandListColumn(state,current)),
//Sort each row
// Then remove duplicates
#"Sort Rows and DeDupe" = List.Distinct(Table.TransformRows(#"Expand Columns", (r) =>
Record.FromList(List.Sort(Record.FieldValues(r)),Record.FieldNames(r)))),
#"Converted to Table" = Table.FromList(#"Sort Rows and DeDupe", Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", Table.ColumnNames(#"Expand Columns"))
in
#"Expanded Column1"
主查询
let
//Read in table and set data type
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"List", Int64.Type}}),
//Call custom function to create the combinations
#"Combos" = fnCombos(#"Changed Type"[List],7)
in #"Combos"
5条答案
按热度按时间rqqzpn5f1#
如果您所说的“excel查询”是指Power Query,那么下面是一个脚本:
算法
=〉56种组合(允许同一组合中的数字重复)
原始数据
重复值组合
编辑以泛化代码
2,000,000
,Excel Power Query无法有效处理,因此需要一段时间才能运行。*我将其编写为名为
fnCombos
的自定义函数自定义函数
fnCombos
*主查询
qybjjes12#
要获取56行:
改进公式:
OP是正确的,应该有56行。您可以检查此here,其中使用的公式为
或在Excel中使用
ego6inou3#
备选方案:
这当前对于3个号码的所有组合是静态设置的,但是如果需要也可以动态设置。
范围内的较大数字可能需要
REPT
的较大第二个参数。omjgkv6w4#
修改了我的答案,以允许组合而不是排列。因此太冗长,但我会离开它。
要用公式写出这一点,可以用途:
C2
中的公式:n8ghc7c15#
这里,使用Excel函数的另一种替代方法。我们使用 * 递归函数 * 生成输入数据的所有索引位置。这种方法 * 精确地生成我们需要的组合集,而无需生成额外的组合集,然后需要删除无效的值集,如重复值等,因此计算步骤*得到优化。
您需要在 Name Manager(如果您不想使用公式,请参见末尾的公式)中输入以下用户
LAMBDA
函数:NEXT_ROW
:**UPDATE:**该功能可简化如下:
其中:
x
,索引位置形状为的数组:1 x n
.m
,需要分布在n
位置的输入值的总数。n
,要分配的索引位置总数i
,要计算的第一个索引位置。在每次迭代中,我们将索引位置减一。当i=0
时,我们完成循环,返回下一行的数组。我们从右到左开始,所以i=n
。NEXT_ROW
,根据输入数组x
返回下一行的索引位置。例如,第一个元素在以下范围内:A1:C1
表示问题中的样本数据,其中m=6
,n=3
,则:这与我们需要的索引位置相对应。
注意:如果您使用的是Excel Web,它不提供对 * 名称管理器 * 的访问,您可以安装以下加载项:Advanced Formula Environment。下面是
NEXT_ROW
函数的视图:有了所有可能的索引位置的序列,生成最终结果是简单的:
我们使用
REDUCE/VSTACK
模式来生成索引位置的整个集合。如何将Excel中表格从垂直转换为水平但长度不同。我们用第一组索引位置初始化
REDUCE
的累加器,这是一个1的常数数组:SEQUENCE(,n,1,0)
,这就是为什么我们需要从所有总组合中少一次迭代:COMBINA(m,n)
,带替换件。下面是输出:
您可以将整个过程封装在新用户
LAMBDA
函数COMBINA_SET
中,并添加到 Name Manager 中,以便将来重用:然后,您可以按如下方式调用它:
我们考虑更一般情况下的其他情景:
1.处理
n=1
和m=1
的特殊情况,我们不需要递归过程,对于这种情况,前面的公式产生了错误。1.允许一般情况,其中输入参数
x
可以是列数组。注意:无论如何你都需要创建
NEXT_ROW
,因为你不能在LET
语句中创建递归函数。你可以 * 克服它 *,遵循这篇文章的建议:LAMBDA Formulaic Recursion: It’s All About ME!(感谢@JosWoolley分享此链接):如果您确实不想使用 Name Manager,而前面的方法使用
ME
解决方案来绕过它,那么您可以在一个公式中包含所有内容: