【问题标题】:Flatten array-valued properties up into their single element value将数组值属性扁平化为它们的单个元素值
【发布时间】:2015-10-04 04:47:24
【问题描述】:

在我的 Node.js 应用程序中,我有一些丑陋的数据:

{"rn":["801"],"destSt":["30089"],"destNm":["95th/Dan Ryan"],"trDr":["5"],"nextStaId":["41430"],"nextStpId":["30276"],"nextStaNm":["87th"],"prdt":["20151003 12:36:48"],"arrT":["20151003 12:38:48"],"isApp":["0"],"isDly":["0"],"flags":[""],"lat":["41.75042"],"lon":["-87.62518"],"heading":["179"]}

如您所见,每个对象属性都莫名其妙地包含一个数组,其值应该直接是该属性的值。

我想将所有内容上移一级,使其看起来像:

{"rn":"801","destSt":"30089","destNm":"95th/Dan Ryan"}

(等)

在任何情况下,这些数组中的任何一个都不会包含一个以上的值。

最好的方法是什么?我试过下划线的展平无济于事。

我不知道如何去谷歌搜索这个。 :)

【问题讨论】:

  • 检查jsfiddle.net/tusharj/2z24p8p0 步骤: 1 遍历对象2. 检查值是否为数组且有长度1 3. 如果是,则将数组替换为其元素。

标签: javascript arrays node.js object underscore.js


【解决方案1】:

试试这个:

var obj = {"rn":["801"],"destSt":["30089"],"destNm":["95th/Dan Ryan"],"trDr":["5"],"nextStaId":["41430"],"nextStpId":["30276"],"nextStaNm":["87th"],"prdt":["20151003 12:36:48"],"arrT":["20151003 12:38:48"],"isApp":["0"],"isDly":["0"],"flags":[""],"lat":["41.75042"],"lon":["-87.62518"],"heading":["179"]},

newObj = Object.keys(obj).reduce(function(result, item){
  result[item] = obj[item][0];  

  return result;
}, {});

【讨论】:

  • 使用reduce 是一种将一个对象映射到另一个对象的相当奇怪的方式。
【解决方案2】:

一种方法是使用 JSON reviver 函数来修改值。这样做的好处是它也可以遍历嵌套对象。

JSON.parse(data, function(key, value) {
  if (Array.isArray(value)) {
    value = value[0];
  }
  return value;
});

演示:http://jsbin.com/hexogaqeja/edit?js,console

【讨论】:

  • 当然,我和其他人一样喜欢 reviver,但在这种情况下,OP 明确指出数组只发生在第一级,虽然看起来值总是字符串,但这种方法赢了'不适用于包含函数、正则表达式等的数组,以防它们存在。另外,虽然我一般不担心微优化,但这会很慢。
【解决方案3】:

遍历键并更改它们的值:

Object.keys(obj).forEach(key => obj[key] = obj[key][0])

这会在原地修改对象。如果您希望创建另一个对象

function unarrayize(obj) {
  var result = {};
  for (var k in obj) result[k] = obj[k][0];
  return result;
}

如果你想使用下划线:

_.mapObject(obj, function(val) { return val[0]; })

【讨论】:

  • 你的意思是Object.keys(obj).forEach(key => obj[key] = obj[key][0])
【解决方案4】:

我可能对数据的复杂性产生了误导(我以为我可以对每个数据进行 for-each 并挑选出来。)

真的,我的数据是一组路线,其中包含一组包含属性的火车。我发布的数据只是火车一号线的数据。

所以我这样做了:

        _.each(routes,function(route, rt_index, list) {
            _.each(route, function (train, train_index,list){
                _.each(train, function (property, property_index,list){
                    routes[rt_index][train_index][property_index] = property[0];
                });
            });
        });

虽然我确信有一种更清洁的方法。

【讨论】:

    【解决方案5】:

    这是使用查询字符串核心模块的一种方法:

    var qs = require('querystring');
    
    var obj = {"rn":["801"],"destSt":["30089"],"destNm":["95th/Dan Ryan"],"trDr":["5"],"nextStaId":["41430"],"nextStpId":["30276"],"nextStaNm":["87th"],"prdt":["20151003 12:36:48"],"arrT":["20151003 12:38:48"],"isApp":["0"],"isDly":["0"],"flags":[""],"lat":["41.75042"],"lon":["-87.62518"],"heading":["179"]};
    
    var newObj = qs.parse(qs.stringify(obj));
    

    可能不是最好的方法,但它可以满足您的需要。

    【讨论】:

    • 嗯该死的,它对我有用吗?之前:{ rn:['801'],destSt:['30089'],destNm:['95th/Dan Ryan'],trDr:['5'],nextStaId:['41430'],(等等)...之后:{ rn:'801',destSt:'30089',destNm:'95th/Dan Ryan',trDr:'5',nextStaId:'41430',(等等)...跨度>
    猜你喜欢
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2021-04-12
    • 1970-01-01
    • 2016-02-12
    相关资源
    最近更新 更多