Javascript 从ES6/ES7中的特定结构化对象数组中提取值

Javascript 从ES6/ES7中的特定结构化对象数组中提取值,javascript,ecmascript-6,filtering,Javascript,Ecmascript 6,Filtering,让我解释一下我的问题 我有如下数据: data: { carType: {key: 'sport', label: 'Sports Car'}, carStyle: {key: 'striped', label: 'Striped (with blabla)'}, carPrice: {key: 'expensive', label: 'Above 500.000$'}, carOptions: [ {key: 'aluminium', label: '

让我解释一下我的问题

我有如下数据:

data: {
  carType:  {key: 'sport',     label: 'Sports Car'},
  carStyle: {key: 'striped',   label: 'Striped (with blabla)'},
  carPrice: {key: 'expensive', label: 'Above 500.000$'},
  carOptions: [
    {key: 'aluminium',   label: 'Chrome Wheel (Available different size)'},
    {key: 'leatherSeat', label: 'Seat Leather from Italy'},
  ]
}
我需要处理这些数据,以便获得与我的对象key///相关联的键值。我在这里遇到的棘手问题是多选

比如:

body: {
 carType: 'sport',
 carStyle: 'striped',
 carPrice: 'expensive',
 carOptions: ['aluminium', 'leatherSeat']
}
我在ES5中做了一些非常冗长的事情。如果可能的话,我想用一些更干净的东西和ES6/ES7特性一起解决这个问题。 谢谢你抽出时间


注:不要考虑数据的内容。它是为这个话题而编造的。在我的例子中,只有数据结构不能修改。

在ES6中,没有什么比在ES5中做得更好的了:

const data = …;
const body = {};
for (const p in data)
    body[p] = Array.isArray(data[p])
      ? data[p].map(x => x.key)
      : data[p].key;

为了进行比较,使用最新的特性(包括实验对象扩展语法),您可以

const body = Object.entries(data).reduce((res, [p, val]) => ({
    ...res,
    [p]: Array.isArray(val)
       ? val.map(({key}) => key)
       : val.key
}), {});

使用ES5,您可以循环使用
数据
对象键,并通过在ech迭代
上进行测试来构建新的
主体
对象:

Object.keys(data).forEach(function(k) {
  if (!Array.isArray(data[k])) {
    body[k] = data[k].key;
  } else {
    body[k] = data[k].map(function(opt) {
      return opt.key;
    });
  }
});
演示:

var数据={
目录类型:{
关键词:“运动”,
标签:“跑车”
},
车型:{
键:'带条纹',
标签:“条纹(带blabla)”
},
卡普里斯:{
关键:“昂贵”,
标签:“超过500.000美元”
},
汽车期权:[{
关键词:“铝”,
标签:“镀铬车轮(可提供不同尺寸)”
},
{
钥匙:“皮革座椅”,
标签:“意大利座椅皮革”
},
]
};
var body={};
Object.keys(数据).forEach(函数(k){
if(!Array.isArray(数据[k])){
body[k]=数据[k]。键;
}否则{
body[k]=数据[k]。映射(函数(opt){
返回opt.key;
});
}
});

控制台日志(主体)
您可以使用
ES6
提供的更清晰可读的函数和操作方法。这里有一些
ES6
可以帮助您解决问题

var数据={
carType:{key:'sport',label:'Sports Car'},
carStyle:{key:'striped',label:'striped(带blabla)},
carPrice:{key:'昂贵',标签:'超过50万美元'},
汽车期权:[
{键:“铝”,标签:“铬轮(可提供不同尺寸)},
{键:'leatherSeat',标签:'Seat Leather from Italy'},
]
}
var obj={};
Object.entries(data).forEach(([key,value])=>{
Object.defineProperty(对象、键、{
value:Array.isArray(value)?value.map(a=>a.key):value.key,
可写:对,
可枚举:正确,
可配置:true
});
});
console.log(obj)
在ES6中,使用

const数据={
目录类型:{
关键词:“运动”,
标签:“跑车”
},
车型:{
键:'带条纹',
标签:“条纹(带blabla)”
},
卡普里斯:{
关键:“昂贵”,
标签:“超过500.000美元”
},
汽车期权:[{
关键词:“铝”,
标签:“镀铬车轮(可提供不同尺寸)”
},
{
钥匙:“皮革座椅”,
标签:“意大利座椅皮革”
},
]
};
const changedData=Object.keys(数据).reduce((tmp,x)=>{
tmp[x]=数组的数据[x]实例?数据[x]。映射(y=>y.key):数据[x]。键;
返回tmp;
}, {});

console.log(changedData)如果您使用lodash,您可以在一行中找到解决方案(1):

_.map(data, (element, index) => Array.isArray(element)?element.map(e=>e.key):element.key)
如果您不喜欢三元溶液,可以使用溶液(2):

如果您不喜欢lodash,但仍希望使用函数编程,则可以使用解决方案(3):

我的意见是使用解决方案(1)或(2)使用lodash,因为它(几乎)具有与数组本机方法相同的语法



使用三元还是不使用取决于您,以及使用常规循环还是不使用

我想知道我是否不明白问题的真正原因,因为我仍然有点不舒服(它影响我的头部),或者因为它真的很难理解?嗨,Morre。我只是想提供一些背景。但是您可以忽略它,并尝试找到一种从第一个数据集传递到第二个数据集的方法:)啊,所以您想要提取密钥。嗯,
map
reduce
覆盖
Object.keys的数组,并在回调函数中进行提取。。。。单键:显而易见,对象数组:内部数组上的另一个
map
reduce
。这应该是要解析的字符串还是javascript对象?这是无效的javascript语法。我的Axnyff错误。我确实更新了我的问题,现在为这个对象添加了一个基于
reduce
的版本,这样他就可以看到所有这些天流行的、他似乎想看到的ES6/7格式的东西:-)你可以在那里使用三元数。谢谢though@Mörre不,我有意识地决定反对这样做——它速度慢,可读性差,而且更复杂。你可以把它贴在你自己的答案中进行比较:-)@Louislecoq啊,另一行保存了。好的。我希望有人能提供下一个语法ES6/ES7。我想还不是每个人都在找它。将接受@Bergi。谢谢
carType
carStyle
应该与
carPrice
@Bergi一样工作是的,它在eS5中,我想表明它几乎是一样的,我编辑了逻辑,谢谢。我想要它是通用的。如果再加上10-20-50-100行类似于carOptions的代码,该怎么办呢。@LouisLecocq您可以使用Bergi的答案中的
Array.isArray()
使其通用。将在IE>9上使用。不会的。Checkout Object.entries()Mozilla文档感谢您的努力。很好的方法为什么在一个非常简单的赋值上使用
Object.defineProperty
?只是为了好玩?或者可能是玩“es6”#对不起,没有理由将
tmp
分配给
ptr
?只是在SO:p的其他地方得到了相同的讨论,都是关于eslint规则的。这是一个可怕的解决方法。如果您想违反该函数的规则,则应该显式禁用该函数的规则。这不是一个解决方法,请参阅eslint文档中的第二个示例。事实上,他们就是这么做的。如果你想的话,你可以禁用这个规则。实际上这似乎更好
_.map(data, (element, index) => {
    if(Array.isArray(element)) {
        return element.map(e=>e.key)
    } else {
        return element.key
    }
})
Object.keys(data).reduce((accumulator, key) => {
    if(Array.isArray(accumulator[key])) {
        accumulator[key] = data[key].map(e=>e.key)
    } else {
        accumulator[key] = data[key].key
    }
    return accumulator
},{})