不可变 JS - 将地图集合转换为列表
Posted
技术标签:
【中文标题】不可变 JS - 将地图集合转换为列表【英文标题】:Immutable JS - converting a collection of Maps to a List 【发布时间】:2021-08-20 10:35:50 【问题描述】:我正在从事的项目中具有以下结构(使用不可变的 JS):
data :[name: 'john', surname: 'smith', children: [name: 'sam', name: 'ben'], name: 'jane', surname: 'jones', children: [name: 'tim', name: 'amy']]
对象通过fromJS()转换为不可变JS。
我需要一个具有以下结构的新对象:
data :[name: 'john', surname: 'smith', children: ['sam','ben'], name: 'jane', surname: 'jones', children: ['tim','amy']]
任何指针都非常感谢。
【问题讨论】:
更新不可变集合有什么意义?你不应该创建一个新列表吗? 我应该将其改写为创建一个新的结果对象。 【参考方案1】:Christian 的纯 JS 答案并不完全适用于 immutable.js 对象,因此这里有一些方法可以使用 immutable.js 的集合 API 来实现。
还有更多选项(例如reduce
),请随时查看the docs;方法说明通常附带示例。
const raw = [name: 'john', surname: 'smith', children: [name: 'sam', name: 'ben'],
name: 'jane', surname: 'jones', children: [name: 'tim', name: 'amy']];
const data = Immutable.fromJS(raw);
function run(name, operation)
let result;
console.time(name);
for(let i=0; i < 50000; i++)
result = operation();
console.timeEnd(name);
console.log(result1.toJS());
run('simple', () =>
// simply updating objects inside a mapping
result1 = data.map(
person => person.update('children',
kidObjs => kidObjs.map(
kid => kid.get('name')
)
)
);
);
run('withMutations and setIn', () =>
// using withMutations and setIn
result2 = data.withMutations(list =>
list.forEach((val, idx) =>
list.setIn(
[idx, 'children'],
val.get('children').map(kid => kid.get('name'))
)
);
);
);
run('withMutations and update', () =>
// slightly faster by using withMutations set/update
result2 = data.withMutations(list =>
list.forEach((val, idx) =>
list.set(idx, val.update('children', kids => kids.map(kid => kid.get('name'))))
);
);
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/4.0.0-rc.14/immutable.min.js"></script>
【讨论】:
【参考方案2】:我会使用 map 和 reduce:
const data = [name: 'john', surname: 'smith', children: [name: 'sam', name: 'ben'],
name: 'jane', surname: 'jones', children: [name: 'tim', name: 'amy']];
var result = data.map(person =>
return name: person.name,
surname: person.surname,
children: person.children.reduce((acc, c) => acc.push(c.name); return acc;, []) );
console.log(result)
【讨论】:
不应该 d.name 等是 d.get('name') 因为它们是不可变的 JS 对象?在我转换为 JS 对象(通过 .toJS())后,我已经发布了结果结构 我不知道 ImmutableJS 的确切语法,但将上面的答案转换为它应该不难。【参考方案3】:类似的东西应该可以工作
data.map(d => d.name, d.surname, children: d.children.map(child => child.name));
【讨论】:
d.name 等不应该是 d.get('name') 因为它们是不可变的 JS 对象。 你可能是对的,我没有关注图书馆以上是关于不可变 JS - 将地图集合转换为列表的主要内容,如果未能解决你的问题,请参考以下文章