Power Query M 从多维列表递归创建 "Flat" 列表

Power Query M Recursively Creating a "Flat" List from a Multidimensional List

在 Power Query M 中,我正在尝试创建一个递归函数,将一团乱麻的多维列表和记录转换为一个平面记录列表,以便可以在 PowerBI 中轻松操作这些记录。

我用过其他语言的递归,但我对使用 M 还很陌生。

混乱的列表和记录在结构上与此类似:

存在一些细微差异,但应该无关紧要。

我希望输出与此类似:

{
    [event1, eventDetail1, payment1, paymentDetails1],
    [event1, eventDetail1, payment1, paymentDetails2],
    [event1, eventDetail1, payment1, paymentDetails3],
    [event1, eventDetail1, payment2, paymentDetails1],
}

针对每个项目继续。

这是我目前的递归函数:

recursiveCollapse = (uncleanedList as list, eventCounter as number, paymentCounter as number, finalList as list) =>
        let
            eventLength = List.Count(uncleanedList),
            firstIf = if eventCounter < eventLength then
                let
                    secondIf = if paymentCounter < List.Count(uncleanedList{eventCounter}[eventPayments]) then
                        finalList = @recursiveCollapse(uncleanedList, eventCounter, paymentCounter + 1, finalList & {
                            [
                                EventName = uncleanedList{eventCounter}[eventDetailName],
                                EventDescription = uncleanedList{eventCounter}[eventDetailDescription],
                                EventSaleStatus = uncleanedList{eventCounter}[eventDetailStatus],
                                EventFirstDate = uncleanedList{eventCounter}[eventDetailFirst],
                                EventLastDate = uncleanedList{eventCounter}[eventDetailLast],
                                PaymentID = uncleanedList{eventCounter}[eventPaymentDetails][refs]{paymentCounter}[id],
                                PaymentName = uncleanedList{eventCounter}[eventPaymentDetails][refs]{paymentCounter}[name],
                                PaymentCreated = uncleanedList{eventCounter}[eventPayments]{paymentCounter}[paymentDetail][created],
                                CustomerEmail = uncleanedList{eventCounter}[eventPayments]{paymentCounter}[paymentDetail][customer][emailAddress],
                                CustomerFirstName = uncleanedList{eventCounter}[eventPayments]{paymentCounter}[paymentDetail][customer][firstName],
                                CustomerLastName = uncleanedList{eventCounter}[eventPayments]{paymentCounter}[paymentDetail][customer][lastName],
                                CustomerPhone = uncleanedList{eventCounter}[eventPayments]{paymentCounter}[paymentDetail][customer][mobilePhone],
                                PaymentStatus = uncleanedList{eventCounter}[eventPayments]{paymentCounter}[paymentDetail][status],
                                PaymentTotal = uncleanedList{eventCounter}[eventPayments]{paymentCounter}[paymentDetail][totalPrice][value]
                            ]
                        })
                    else
                        finalList = @recursiveCollapse(uncleanedList, eventCounter + 1, 0, finalList)
                in
                    finalList
            else
                finalList
        in
            finalList,
    dataTable = recursiveCollapse(allEventsLinks, 0, 0, {})
in
    dataTable

在这个阶段 "dataTable" 只是 return 编辑为空 table。

我认为问题是由于 "finalList" 没有通过函数的递归调用正确地 returned。 M 没有 return 关键字,所以我不知道从这里该怎么做。

感谢任何帮助。

谢谢

我想通了。

对于任何需要帮助的人,这是我的解决方案:

recursiveCollapse = (uncleanedList as list, eventCounter as number, paymentCounter as 
number, finalList as list) =>
    let
        returnList = 
            let
                eventLength = List.Count(uncleanedList),
                eventIf = if eventCounter < eventLength then
                    let
                        eventReturn = if paymentCounter + 1 < List.Count(uncleanedList{eventCounter}[eventPayments]) then
                            let
                            addRow = 
                                finalList & 
                                {
                                    [
                                        EventName = uncleanedList{eventCounter}[eventDetailName],
                                        EventDescription = uncleanedList{eventCounter}[eventDetailDescription],
                                        EventSaleStatus = uncleanedList{eventCounter}[eventDetailStatus],
                                        EventFirstDate = uncleanedList{eventCounter}[eventDetailFirst],
                                        EventLastDate = uncleanedList{eventCounter}[eventDetailLast],
                                        PaymentID = uncleanedList{eventCounter}[eventPaymentDetails][refs]{paymentCounter + 1}[id],
                                        PaymentName = uncleanedList{eventCounter}[eventPaymentDetails][refs]{paymentCounter + 1}[name],
                                        PaymentCreated = uncleanedList{eventCounter}[eventPayments]{paymentCounter + 1}[paymentDetail][created],
                                        CustomerEmail = uncleanedList{eventCounter}[eventPayments]{paymentCounter + 1}[paymentDetail][customer][emailAddress],
                                        CustomerFirstName = uncleanedList{eventCounter}[eventPayments]{paymentCounter + 1}[paymentDetail][customer][firstName],
                                        CustomerLastName = uncleanedList{eventCounter}[eventPayments]{paymentCounter + 1}[paymentDetail][customer][lastName],
                                        CustomerPhone = uncleanedList{eventCounter}[eventPayments]{paymentCounter + 1}[paymentDetail][customer][mobilePhone],
                                        PaymentStatus = uncleanedList{eventCounter}[eventPayments]{paymentCounter + 1}[paymentDetail][status],
                                        PaymentTotal = uncleanedList{eventCounter}[eventPayments]{paymentCounter + 1}[paymentDetail][totalPrice][value]
                                    ]
                                },
                            recursion = @recursiveCollapse(uncleanedList, eventCounter, paymentCounter + 1, addRow)
                        in
                            recursion
                    else
                        let
                            recursion = @recursiveCollapse(uncleanedList, eventCounter + 1, 0, finalList)
                        in
                            recursion
                in
                    eventReturn
            else
                finalList
        in
            eventIf
in
    returnList,

dataTable = Table.FromList(recursiveCollapse(allEventsLinks, 0, 0, {}), Record.FieldValues, {
    "EventName",
    "EventDescription",
    "EventSaleStatus",
    "EventFirstDate",
    "EventLastDate",
    "PaymentID",
    "PaymentName",
    "PaymentCreated",
    "CustomerEmail",
    "CustomerFirstName",
    "CustomerLastName",
    "CustomerPhone",
    "PaymentStatus",
    "PaymentTotal"
})
in
dataTable