Javascript如何从映射返回数组
我有下面的JsonJavascript如何从映射返回数组,javascript,arrays,ramda.js,Javascript,Arrays,Ramda.js,我有下面的Json var myjson = [{ "files": [ { "domain": "d", "units": [ { "key": "key1", "type": "2"
var myjson = [{
"files": [
{
"domain": "d",
"units": [
{
"key": "key1",
"type": "2"
},
{
"key": "key2",
"type": "2"
},
{
"key": "key3",
"type": "2"
}]
},
{
"domain": "d1",
"units": [
{
"key": "key11",
"type": "2"
},
{
"key": "key12",
"type": "2"
},
{
"key": "key13",
"type": "2"
}]
}]
},
{
"files": [
{
"domain": "d",
"units": [
{
......
我想从这个Json数组创建一个新数组。数组的长度将是这个Json对象中的“单位”数
所以我需要提取“单位”,并从父对象添加一些数据
units: [{
domain: "",
type: "",
key: ""
}, {
domain: "",
type: "",
key: ""
},
{
domain: "",
type: "",
key: ""
}
....
];
我想我大概可以这样做:
var res = [];
myjson.forEach(function(row) {
row.files.forEach(function(tfile) {
tfile.units.forEach(function(unit) {
var testEntity = {
domain: tfile.domain,
type : unit.type,
key: unit.key
};
res.push(testEntity);
});
});
});
但是它很难阅读,看起来也不太好。我想做一些类似的事情:
var RESULT = myjson.map(function(row) {
return row.files.map(function(tfile) {
return tfile.units.map(function(unit) {
return {
domain: tfile.domain,
type : unit.type,
key: unit.key
};
});
});
});
但这不起作用,看起来也不好。是否有任何方法可以做到这一点,也许是以更具声明性的方式。希望Ramda.js能帮上忙
一般来说,有什么好方法可以以可读的方式从任何嵌套的json中获取数据吗
实施类似于:
nestedjson.findAllOnLastlevel(function(item){
return {
key : item.key,
type: type.key,
domain : item.parent.domain}
});
或者以某种方式展平此json,以便将来自所有父对象的所有属性移动到leafs子对象。myjson.flatte(“files.units”)
杰斯宾
非常感谢像这样的事情应该行得通
.reduce
适用于此类情况
const allUnits = myjson.reduce((acc, anonObj) => {
const units = anonObj.files.map(fileObj => {
return fileObj.units.map(unit => {
return {...unit, domain: fileObj.domain})
})
return [...acc, ...units]
}, [])
请注意,这依赖于阵列扩展和对象扩展,这是ES6的功能,并非每个平台都支持
如果您不能使用ES6,这里有一个ES5实现。没有那么漂亮,但做了同样的事情:
var allUnits = myjson.reduce(function (acc, anonObj) {
const units = anonObj.files.map(function(fileObj) {
// for each fileObject, return an array of processed unit objects
// with domain property added from fileObj
return fileObj.units.map(function(unit) {
return {
key: unit.key,
type: unit.type,
domain: fileObj.domain
}
})
})
// for each file array, add unit objects from that array to accumulator array
return acc.concat(units)
}, [])
试试这个
var myjson=[{
“文件”:[{
“域”:“d”,
“单位”:[{
“键”:“键1”,
“类型”:“2”
}, {
“键”:“键2”,
“类型”:“2”
}, {
“键”:“键3”,
“类型”:“2”
}]
},
{
“域”:“d1”,
“单位”:[{
“键”:“键11”,
“类型”:“2”
}, {
“键”:“键12”,
“类型”:“2”
}, {
“键”:“键13”,
“类型”:“2”
}]
}
]
}];
//首先筛选出排除单元的属性
var结果=[];
forEach(函数(obj){
forEach(函数(obj2){
结果=结果.concat(obj2.units.map)(函数(单位){
unit.domain=obj2.domain;
返回单元;
}));
});
});
控制台日志(结果)
这里可以使用的函数是Ramda的函数,而不是R.map
。您可以将R.chain
视为一种映射列表的方法,该方法使用一个函数返回另一个列表,然后将结果列表平铺在一起
// get a list of all files
const listOfFiles =
R.chain(R.prop('files'), myjson)
// a function that we can use to add the domain to each unit
const unitsWithDomain =
(domain, units) => R.map(R.assoc('domain', domain), units)
// take the list of files and add the domain to each of its units
const result =
R.chain(file => unitsWithDomain(file.domain, file.units), listOfFiles)
如果您想更进一步,还可以使用which来帮助组合函数,这些函数在每个给定函数之间的行为类似于R.chain
// this creates a function that accepts the `myjson` list
// then passes the list of files to the second function
// returning the list of units for each file with the domain attached
const process = pipeK(prop('files'),
f => map(assoc('domain', f.domain), f.units))
// giving the `myjson` object produces the same result as above
process(myjson)
纯JS足以在简单的一行程序中产生结果。我不会为了这份工作去碰任何图书馆。我这里有两种方法。第一个是reduce.reduce.map链,第二个是reduce.map.map链。这是代码
var myjson=[{“文件”:[{“域”:“d”,“单位”:[{“键”:“键1”,“类型”:“2”},{“键2”,“类型”:“键3”,“类型”:“2”},{“域”:“d1”,“单位”:[{“键”:“键11”,“类型”:“2”},{“键12”,“类型”:“2”},{“键”:“键13”,“类型”:“2”},{“键2”},},{“文件”:“域”:“e单位”:“键1”,“类型”:“键1”,“键2”{“键2”},{“键2”},{“键2”},{“2”},{“域”:“e1”,“单元”:[{“键”:“键11”,“类型”:“2”},{“键”:“键12”,“类型”:“2”},{“键”:“键13”,“类型”:“2”}]}],
units=myjson.reduce((p,c)=>c.files.reduce((f,s)=>f.concat(s.units.map(e=>(e.domain=s.domain,e))),p),[]);
units2=myjson.reduce((p,c)=>p.concat(…c.files.map(f=>f.units.map(e=>(e.domain=f.domain,e))),[];
控制台日志(单位);
console.log(units2);
所以你需要一个工作版本,你已经有了,或者一个好看的版本,可以用ES6风格完成?现在我有了一个工作版本,但我做了很多这种“嵌套json操作”“正在考虑一种适当的方法。甚至可能是一些一般的方法。我提供的json被简化了。可能更深。另外,新的“=>”在我的例子中不可用。主要问题是要知道迭代哪个属性。您可以使用递归方法给出路径,但至少需要重新组合属性。works可以提供不需要var result=[]的内容;可以吗?以不变的方式?映射总是返回一个结果吗?它是否可以返回“类多”域
键是missed@Ant所有三个级别的映射都将返回类似于[[[{key:'key1',value:'1'}]]]
的内容,要克服这一问题,您需要编写代码来接受单个项,然后将其连接到数组中。因为你想要一个更短的代码,所以我不能让它比这个更短:)我有ES5,没有办法改变它:(看起来不错-我简化了我的json,如果我有多(五)个属性需要在同一个地方关联,比如domain?和第一级prop1上的几个其他属性:“值”,文件:{…我在这里添加了var result=R.pipe(R.chain(函数(p){返回R.map(R.assoc('parent',p,p.files)})、R.chain(函数(p){返回R.map(R.assoc('parent',p,p.units)})、R.chain(函数(k){返回{域:k.parent.domain,prop1:k.parent.parent.prop1,键:k.key}}))(myjson)
是的,这需要在每个步骤中将属性值作为状态线程化。