本文深入探討了如何利用groovy的強大集合方法,特別是`groupby`和`collect`,將一個扁平的map列表高效地轉(zhuǎn)換為具有父子層級結(jié)構(gòu)的嵌套列表。通過一個具體的示例,文章詳細演示了如何根據(jù)共同的鍵(如`coveragetype`)對數(shù)據(jù)進行分組,并進一步重構(gòu)每個分組,生成包含父級標識和子級詳細信息的新結(jié)構(gòu),從而實現(xiàn)復(fù)雜的數(shù)據(jù)重塑需求。
在數(shù)據(jù)處理和轉(zhuǎn)換中,我們經(jīng)常會遇到將扁平化的數(shù)據(jù)結(jié)構(gòu)重塑為更具組織性和層次感的需求。例如,一個包含多個獨立記錄的列表,我們可能需要根據(jù)某個共同的屬性將這些記錄分組,并將其組織成一個父子(或主從)結(jié)構(gòu)。傳統(tǒng)的迭代和條件判斷方法可能導(dǎo)致代碼冗長且效率低下。Groovy作為一種動態(tài)語言,提供了豐富的集合操作方法,能夠以簡潔、聲明式的方式解決這類數(shù)據(jù)重塑問題。
假設(shè)我們有一個fakeList,其中包含多個保險覆蓋類型的記錄:
def fakeList = [ [coverageType: 'health', amount: 9, expireDate: 2020], [coverageType: 'insurance', amount: 10, expireDate: 2020], [coverageType: 'health', amount: 9, expireDate: 2021], ]
我們的目標是將這個列表轉(zhuǎn)換為以下結(jié)構(gòu):
[ [parent: 'health', childs: [ [coverage: 'health', amount: '9', expireDate: '2020'], [coverage: 'health', amount: '9', expireDate: '2021'], ] ], [parent: 'insurance', childs: [ [coverage: 'insurance', amount: '10', expireDate: '2020'] ] ] ]
這種結(jié)構(gòu)將所有coverageType相同的記錄歸入同一個parent下,并作為其childs列表的元素。
Groovy的groupBy和collect是實現(xiàn)這種數(shù)據(jù)重塑的關(guān)鍵工具。groupBy用于將集合中的元素根據(jù)某個屬性進行分組,而collect則用于對集合中的每個元素進行轉(zhuǎn)換,生成一個新的集合。
首先,我們使用groupBy方法將fakeList中的元素根據(jù)coverageType屬性進行分組。groupBy方法會返回一個Map,其中鍵是分組的依據(jù)(coverageType的值),值是符合該鍵的所有原始元素的列表。
def groupList = fakeList.groupBy { it.coverageType }
執(zhí)行上述代碼后,groupList的結(jié)構(gòu)將大致如下:
// groupList 的中間結(jié)果 [ 'health': [ [coverageType: 'health', amount: 9, expireDate: 2020], [coverageType: 'health', amount: 9, expireDate: 2021] ], 'insurance': [ [coverageType: 'insurance', amount: 10, expireDate: 2020] ] ]
接下來,我們對groupList這個Map進行迭代,并使用collect方法將其轉(zhuǎn)換為我們期望的父子結(jié)構(gòu)列表。collect方法接受一個閉包,該閉包對Map的每個條目(鍵值對)進行處理,并返回一個新的元素。
即構(gòu)數(shù)智人是由即構(gòu)科技推出的AI虛擬數(shù)字人視頻創(chuàng)作平臺,支持數(shù)字人形象定制、短視頻創(chuàng)作、數(shù)字人直播等。
在collect的閉包中,我們可以訪問到每個分組的coverageType(作為coverageType參數(shù))和對應(yīng)的原始項目列表(作為items參數(shù))。我們可以創(chuàng)建一個新的Map來表示父級結(jié)構(gòu),其中parent鍵對應(yīng)coverageType。
// ... 承接上文的 groupList .collect { coverageType, items -> def map = [:] map.'parent' = coverageType // ... 接下來構(gòu)建 childs }
對于每個父級結(jié)構(gòu),其childs鍵的值應(yīng)該是一個列表,包含所有屬于該coverageType的原始項目。我們需要再次使用collect方法,遍歷items列表,將每個原始Map轉(zhuǎn)換為我們期望的子級Map格式。
// ... 承接上文的 map.'parent' = coverageType map.'childs' = items.collect { item -> def childMap = [:] childMap.'coverage' = coverageType // 或者 item.coverageType childMap.'amount' = item.amount as String // 注意類型轉(zhuǎn)換 childMap.'expireDate' = item.expireDate as String // 注意類型轉(zhuǎn)換 childMap } map // 返回完整的父子結(jié)構(gòu)Map }
這里需要注意的是,我們對amount和expireDate進行了as String的類型轉(zhuǎn)換,以確保輸出格式與預(yù)期一致。
將上述步驟整合起來,完整的Groovy代碼如下:
def fakeList = [ [coverageType: 'health', amount: 9, expireDate: 2020], [coverageType: 'insurance', amount: 10, expireDate: 2020], [coverageType: 'health', amount: 9, expireDate: 2021], ] def groupList = fakeList.groupBy { it.coverageType } .collect { coverageType, items -> def map = [:] map.'parent' = coverageType map.'childs' = items.collect { item -> def childMap = [:] childMap.'coverage' = coverageType // 保持與父級一致,或使用 item.coverageType childMap.'amount' = item.amount as String // 將數(shù)字轉(zhuǎn)換為字符串 childMap.'expireDate' = item.expireDate as String // 將數(shù)字轉(zhuǎn)換為字符串 childMap } map } println groupList
運行上述代碼,將得到以下結(jié)果:
[ [parent:health, childs:[[coverage:health, amount:9, expireDate:2020], [coverage:health, amount:9, expireDate:2021]]], [parent:insurance, childs:[[coverage:insurance, amount:10, expireDate:2020]]] ]
這個結(jié)果精確地匹配了我們預(yù)期的父子層級結(jié)構(gòu),每個coverageType都成為了一個parent,其下方的childs列表包含了所有相關(guān)的原始記錄,并按照指定的格式進行了轉(zhuǎn)換。
map.'childs' = items.collect { item -> [item.coverageType, item.amount as String, item.expireDate as String] }
通過結(jié)合使用Groovy的groupBy和collect方法,我們可以優(yōu)雅且高效地解決復(fù)雜的數(shù)據(jù)重塑問題。這種聲明式的編程風(fēng)格不僅使代碼更簡潔,也提高了其可讀性和可維護性。掌握這些強大的集合操作,是成為一名高效Groovy開發(fā)者的關(guān)鍵一步。在處理類似將扁平數(shù)據(jù)轉(zhuǎn)換為層次結(jié)構(gòu)的需求時,優(yōu)先考慮利用Groovy提供的這些內(nèi)置功能,將大大提升開發(fā)效率和代碼質(zhì)量。
以上就是Groovy數(shù)據(jù)重塑:將扁平列表按鍵分組并構(gòu)建嵌套結(jié)構(gòu)的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進程會占用資源并降低性能。幸運的是,許多工具可以讓 Windows 保持平穩(wěn)運行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號