我正在寻找一种更简单的解决方案,以函数式编程风格将字典和列表组合成单个列表。字典、列表和预期结果如下所示:
const myDictionary = new Map<string, number>([
['a', 4],
['b', 0],
['c', 3]
])
const myList = [
'a',
'b',
'c'
]
const expectedResult = [
[
{'index': 0, 'payload': 'a0'},
{'index': 1, 'payload': 'a1'},
{'index': 2, 'payload': 'a2'},
{'index': 3, 'payload': 'a3'}
],
[],
[
{'index': 4, 'payload': 'c0'},
{'index': 5, 'payload': 'c1'},
{'index': 6, 'payload': 'c2'}
]
]
如您所见,
expectedResult
内部列表的项目数是可变的。在此示例中,它等于地图 myDictionary
的值,但这只是一个示例。创建这些内部列表项的函数是确定性的,但必须以某种方式计算、匹配、组合这些值......
我的问题是,我怎样才能以实用的方式做到这一点。我可以在这里做这样的事情(我在这个项目中使用 Randa):
给定一个可以转换每个列表项的函数:
const transformListItem = (char: string, offset: number, dictionary: Map<string, number>) =>
range(0, dictionary.get(char)).map(i => ({
'index': i + offset,
'payload': `${char}${i}`
}))
那么这就是我将其组合在一起的方式:
const transformList = (list: string[], dictionary: Map<string, number>) =>
list.map((char, listItemIndex) => {
const listPriorToThisItem = slice(0, listItemIndex, list)
const transformedListPriorThisItem = transformList(listPriorToThisItem, dictionary)
const indexOffset = sum(transformedListPriorThisItem.map(a => a.length))
return transformListItem(char, indexOffset, dictionary)
}
const result = transformList(myList, myDictionary)
但是使用这种方法,每个列表项都会进行多次计算。所以我的问题是:如何实现这一点而不必进行两次(或多次)计算。我知道记忆的可能性,但它似乎变得更加复杂。非功能性解决方案是迭代索引变量:
const transformList = (list: string[], dictionary: Map<string, number>) => {
let indexOffset = 0
return list.map(char => {
const transformedItem = transformListItem(char, indexOffset, dictionary)
indexOffset += transformedItem.length
return transformedItem
}
}
const result = transformList(myList, myDictionary)
FP 中有没有更简单的模式来实现这一点?
mapAccum
函数应该允许您映射项目,同时存储下一个项目的index
:
const { range, mapAccum } = R
const transformListItem = (char, offset, dictionary) =>
range(0, dictionary.get(char)).map(i => ({
'index': i + offset,
'payload': `${char}${i}`
}))
const transformList = (list, dictionary) =>
mapAccum(
(index, char) => [
index + dictionary.get(char),
transformListItem(char, index, dictionary)
],
0,
list
)[1]
const myDictionary = new Map([['a', 4], ['b', 0], ['c', 3]])
const myList = ['a', 'b', 'c']
const result = transformList(myList, myDictionary)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.29.1/ramda.min.js" integrity="sha512-PVSAmDFNqey8GMII8s9rjjkCFvUgzfsfi8FCRxQa3TkPZfdjCIUM+6eAcHIFrLfW5CTFAwAYS4pzl7FFC/KE7Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>