【问题标题】:Creating Arrays of Objects in nested Objects with Javascript使用 Javascript 在嵌套对象中创建对象数组
【发布时间】:2015-10-18 11:57:54
【问题描述】:

给定以下 javascript 对象结构,通常是 firebase 返回的内容

var data = {
  'id1' : {
    'fname' : 'value',
    'lname' : 'value',
    'things' : {
      'thing1' : {
        'brand' : 'value',
        'name' : 'value'
      },
      'thing2' : {
        'brand' : 'value',
        'name' : 'value'
      },
      'thing3' : {
        'brand' : 'value',
        'name' : 'value'
      }
    }
  },
  'id2' : {
    'fname' : 'value',
    'lname' : 'value',
    'things' : {
      'thing1' : {
        'brand' : 'value',
        'name' : 'value'
      },
      'thing2' : {
        'brand' : 'value',
        'name' : 'value'
      },
      'thing3' : {
        'brand' : 'value',
        'name' : 'value'
      }
    }
  }
};

你会怎样把它转换成

[
  {
    'fname' : 'value',
    'lname' : 'value,
    'things' : [
      {
        'brand' : 'value',
        'name' : 'value'
      },
      {
        'brand' : 'value',
        'name' : 'value'
      },
      {
        'brand' : 'value',
        'name' : 'value'
      }
    ]
  },
  {
    'fname' : 'value',
    'lname' : 'value,
    'things' : [
      {
        'brand' : 'value',
        'name' : 'value'
      },
      {
        'brand' : 'value',
        'name' : 'value'
      },
      {
        'brand' : 'value',
        'name' : 'value'
      }
    ]
  }
]

请记住,嵌套对象可能比这更深。将嵌套结构转换为数组的实现有很多,但我还没有看到有人进行这种特定的转换。我一直在绞尽脑汁,只是非常接近,但还没有做到恰到好处。

我已经有了这段代码,它对像“事物”这样的更深层次的对象没有任何作用。

var collection = [];
for(key in data) {
  collection.push(data[key]);
}

我正在努力使其递归。

编辑 我想它需要被包裹在一个可以调用自身的函数中,以便它可以递归。

【问题讨论】:

  • @FrankvanPuffelen 这不是那个的副本。我已经有了那个代码。我正在寻找它更深入并迭代对象的所有级别。您链接到的问题和答案正是我已经在做的事情。
  • 关闭投票已撤回,请在下方回答。
  • 键名是否应该表明数组排序?例如(id1,id2 / thing1 thing2)如果是这样,规则是什么?
  • @LukeP 键不表示订购。该对象在设置为数据变量之前在服务器上排序。

标签: javascript


【解决方案1】:

这是一个不需要知道键的解决方案,假设您要转换每个其他级别的嵌套:

function toArrayOfObjects(obj) {
  var collection = [];
  for (key in obj) {
    var value = obj[key];
    if (typeof value === 'object' && !Array.isArray(value)) {
      var childObj = {};
      for (childKey in value) {
        var childValue = value[childKey];
        if (typeof childValue === 'object' && !Array.isArray(childValue)) {
          childObj[childKey] = toArrayOfObjects(childValue);
        } else {
          childObj[childKey] = childValue;
        }
      }
      collection.push(childObj);
    } else {
      collection.push(value);
    }
  }
  return collection;
}

【讨论】:

    【解决方案2】:

    这样的事情应该可以解决问题:

    function convert(object, propNamesToConvert) {
      var array = [];
      Object.keys(object).forEach(function(key) {
        array.push(visit(object[key], propNamesToConvert));
      });
      return array;
    }
    
    function visit(object, propNamesToConvert) {
      var result = {};
      Object.keys(object).forEach(function(key) {
        var value = object[key];
        if (typeof(value) === 'object') {
          // objects are either 'things to be converted' or we need to traverse further down the rabbit hole
          if (propNamesToConvert.indexOf(key) >= 0) {
            value = convert(value, propNamesToConvert);
          }
          else {
            value = visit(value, propNamesToConvert);
          }
        }
        result[key] = value;
      });
      return result;
    }
    
    console.log(JSON.stringify(visit(data, ['things'])));
    

    它可能会大大缩短,但这很有效。将硬编码的['things'] 翻译成不易维护的东西会方式更好。

    var data = {
      'id1' : {
        'fname' : 'value',
        'lname' : 'value',
        'things' : {
          'thing1' : {
            'brand' : 'value',
            'name' : 'value'
          },
          'thing2' : {
            'brand' : 'value',
            'name' : 'value'
          },
          'thing3' : {
            'brand' : 'value',
            'name' : 'value'
          }
        }
      },
      'id2' : {
        'fname' : 'value',
        'lname' : 'value',
        'things' : {
          'thing1' : {
            'brand' : 'value',
            'name' : 'value'
          },
          'thing2' : {
            'brand' : 'value',
            'name' : 'value'
          },
          'thing3' : {
            'brand' : 'value',
            'name' : 'value'
          }
        }
      }
    };
    
    function convert(object, propNamesToConvert) {
      var array = [];
      Object.keys(object).forEach(function(key) {
        array.push(visit(object[key], propNamesToConvert));
      });
      return array;
    }
    
    function visit(object, propNamesToConvert) {
      var result = {};
      Object.keys(object).forEach(function(key) {
        var value = object[key];
        if (typeof(value) === 'object') {
          if (propNamesToConvert.indexOf(key) >= 0) {
            value = convert(value, propNamesToConvert);
          }
          else {
            value = visit(value, propNamesToConvert);
          }
        }
        result[key] = value;
      });
      return result;
    }
    
    console.log(JSON.stringify(visit(data, ['things'])));
    <script src="https://getfirebug.com/firebug-lite-debug.js"></script>

    【讨论】:

    • 谢谢弗兰克。布伦特的解决方案和我将选择作为答案的解决方案不需要密钥知识。
    • 听起来不错。请记住,这两种解决方案都对您的数据结构进行了假设(一种是隐式假设,另一种是显式假设)。这样的选择是必要的,因为您正在处理一个无模式模型,因此从 JSON 数据本身不清楚哪些级别需要展平为数组。
    【解决方案3】:

    var newData = [];
    var dataKeys = Object.keys(data);
    for(var i=0; i<dataKeys.length; i++)
    {
        newData.push(data[dataKeys[i]]);
    }

    【讨论】:

    • 这不会处理像“事物”这样更深层次的对象。
    猜你喜欢
    • 1970-01-01
    • 2019-10-06
    • 2019-09-23
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 2017-02-14
    • 1970-01-01
    相关资源
    最近更新 更多