代码之家  ›  专栏  ›  技术社区  ›  SBB

JavaScript将指定的单个对象转换为数组

  •  2
  • SBB  · 技术社区  · 8 年前

    我正在处理一些 JSON

    我的问题是,在处理循环时,必须尝试并处理这一问题。

    示例数据:

    // Single result from DB
    var obj = {
      "records": {
        "recordID": 1,
        "recordName": 'test'
      }
    }
    
    // Multiple results from DB
    var obj = {
      "records": [{
        "recordID": 1,
        "recordName": 'test'
      }, {
        "recordID": 2,
        "recordName": 'test again'
      }]
    }
    


    由于我的一些对象相当大,我正在尝试提出一个函数,当我在处理之前从数据库中获取对象时,可以使用该函数初始化对象。

    // Input 
    var obj = {
        "records": {
            "recordID": 1,
            "recordName": 'test'
        },
        "photos": {
            "photoID": 1,
            "photoName": 'test flower'
        },
        "leaveMeAlone": {
            "nopeID": 1,
            "nopeName": 'tester'
        }
    }
    
    
    function convertToArray(obj) {
    
        var keysToArray = ['records', 'photos'];
    
        // Loop over keys
        for (var k in obj) {
    
            // Properties
            if (obj.hasOwnProperty(k)) {
    
                // This key is in our array. 
                if (keysToArray.indexOf(k) > -1) {
    
                    // If this is a single object, turn it into an array containing a single object
                    if (!Array.isArray(obj[k])) {
                        // Turn this value into an array of the single object
                        /* Stuck Here */
                    }
                }
            }
        }
    
        /* Return 
        
        var obj = {
            "records": [{
                "recordID": 1,
                "recordName": 'test'
            }],
            "photos": [{
                "photoID": 1,
                "photoName": 'test flower'
            }],
            "leaveMeAlone": {
                "nopeID": 1,
                "nopeName": 'tester'
            }
        }
        */
    
    }
    
    // run
    convertToArray(obj);
    3 回复  |  直到 8 年前
        1
  •  4
  •   Ankush Jain    8 年前

    你可以使用下面我创建的方法。它将检查对象是否为数组。否则,它会将对象放入数组中并返回。

    function convertToArray(obj) {
        if (obj.records instanceof Array) {
            return obj.records;
        } else {
            return [obj.records];
        }
    }
    

    https://jsfiddle.net/r4otdrq0/

        2
  •  1
  •   Nina Scholz    8 年前

    您可以通过将给定属性转换为数组(如果还不是数组的话)来采取迭代和递归方法。

    如果所有键都是唯一的,则可以使用提前返回,方法是删除数组的属性,或将路径从深度优先更改为广度优先搜索。

    function convert(object, keys) {
        Object.keys(object).forEach(function (k) {
            if (object[k] && typeof object[k] === 'object') {
                convert(object[k], keys);
            }
            if (keys.indexOf(k) !== -1 && !Array.isArray(object[k])) {
                object[k] = [object[k]];
            }
        });
    }
    
    var object = { records: { recordID: 1, recordName: 'test' }, photos: { photoID: 1, photoName: 'test flower' }, leaveMeAlone: { nopeID: 1, nopeName: 'tester' }, nested: { convert: { foo: 1, bar: 2 } } },
        keys = ['records', 'photos', 'convert'];
    
    convert(object, keys);
    
    console.log(object);
    .as-console-wrapper { max-height: 100% !important; top: 0; }
        3
  •  0
  •   skirtle    8 年前

    注意,我已经替换了内联的值,因此传入的对象发生了变化。除此之外,我希望这是非常不言自明的。

    // Input 
    var obj = {
        "records": {
            "recordID": 1,
            "recordName": 'test'
        },
        "photos": {
            "photoID": 1,
            "photoName": 'test flower'
        },
        "leaveMeAlone": {
            "nopeID": 1,
            "nopeName": 'tester'
        }
    }
    
    function convertToArray(obj) {
        var keysToArray = ['records', 'photos'];
    
        keysToArray.forEach(function(key) {
            if (key in obj && !Array.isArray(obj[key])) {
                obj[key] = [obj[key]];
            }
        });
    
        return obj;
    }
    
    console.log(convertToArray(obj));

    function convertToArray(obj, keysToConvert) {
      if (Array.isArray(obj)) {
        obj.forEach(function(entry) {
          convertToArray(entry, keysToConvert);
        });
      }
      else if (obj && typeof obj === 'object') {
        Object.keys(obj).forEach(function(key) {
          if (keysToConvert.indexOf(key) !== -1 && !Array.isArray(obj[key])) {
            obj[key] = [obj[key]];
          }
    
          convertToArray(obj[key], keysToConvert);
        });
      }
    
      return obj;
    }
    
    var obj = {
      "data": {
        "VersionForTarget": "1",
        "rules": {
          "rule": {
            "RuleParentID": "84",
            "RuleVersionID": "2",
            "MappedValue": "1",
            "ProcessingOrder": "1",
            "MetaInsertUtc": "2017-03-03T17:54:34.643",
            "Value": "Recorded",
            "IsRuleRetired": "0",
            "UserImpactCount": "27130",
            "attributes": {
              "attribute": {
                "AttributeID": "2",
                "AttributeName": "Role",
                "attributeDetails": {
                  "attributeDetail": [{
                      "RuleDetailID": "10964",
                      "AttributeID": "2",
                      "OperatorID": "3",
                      "AttributeValue": "172",
                      "RuleParentID": "84",
                      "Value": "Account Manager",
                      "IsValueRetired": "0",
                      "OperatorName": "In List",
                      "SqlOperator": "IN"
                    },
                    {
                      "RuleDetailID": "10966",
                      "AttributeID": "2",
                      "OperatorID": "3",
                      "AttributeValue": "686",
                      "RuleParentID": "84",
                      "Value": "Agent",
                      "IsValueRetired": "0",
                      "OperatorName": "In List",
                      "SqlOperator": "IN"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
    
    console.log(convertToArray(obj, ['rule', 'attribute', 'attributeDetail']))