将JS对象(键和值)展平为单个深度数组的最佳方法

ddo*_*ngo 10 javascript arrays object

我编写了这个小函数来获取对象的所有键和值并将它们存储到数组中.该对象可能包含数组作为值...

Object { 0: [1,2,3,4] }[0,1,2,3,4]转换的所有元素为整数

我想知道是否有更快/更清洁的方法:

function flattenObject(obj) {
    // Returns array with all keys and values of an object
    var array = [];
    $.each(obj, function (key, value) {
        array.push(key);
        if ($.isArray(value)) {
            $.each(value, function (index, element) {
                array.push(element);
            });
        }
        else {
            array.push(value);
        }
    });

    return array
}
Run Code Online (Sandbox Code Playgroud)

Mut*_*nan 23

我想把我的深层物体压平到一个深度.上述解决方案均不适合我.

我的意见:

{
    "user": {
        "key_value_map": {
            "CreatedDate": "123424",
            "Department": {
                "Name": "XYZ"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

预期产量:

{
    "user.key_value_map.CreatedDate": "123424",
    "user.key_value_map.Department.Name": "XYZ"
}
Run Code Online (Sandbox Code Playgroud)

对我有用的代码:

function flattenObject(ob) {
    var toReturn = {};

    for (var i in ob) {
        if (!ob.hasOwnProperty(i)) continue;

        if ((typeof ob[i]) == 'object' && ob[i] !== null) {
            var flatObject = flattenObject(ob[i]);
            for (var x in flatObject) {
                if (!flatObject.hasOwnProperty(x)) continue;

                toReturn[i + '.' + x] = flatObject[x];
            }
        } else {
            toReturn[i] = ob[i];
        }
    }
    return toReturn;
}
Run Code Online (Sandbox Code Playgroud)


Tof*_*del 21

这个答案是对@Muthukrishnan 的答案的改进

如果要将对象深度展平,则将值输出到以前一个对象中值的路径为键的一级深度对象中

(例如:{ foo: { bar: 'baz'} }=> { 'foo.bar': 'baz' }

以下是如何有效地做到这一点:

/**
 * @param ob Object                 The object to flatten
 * @param prefix String (Optional)  The prefix to add before each key, also used for recursion
 **/
function flattenObject(ob, prefix = false, result = null) {
  result = result || {};

  // Preserve empty objects and arrays, they are lost otherwise
  if (prefix && typeof ob === 'object' && ob !== null && Object.keys(ob).length === 0) {
    result[prefix] = Array.isArray(ob) ? [] : {};
    return result;
  }

  prefix = prefix ? prefix + '.' : '';

  for (const i in ob) {
    if (Object.prototype.hasOwnProperty.call(ob, i)) {
      if (typeof ob[i] === 'object' && ob[i] !== null) {
        // Recursion on deeper objects
        flattenObject(ob[i], prefix + i, result);
      } else {
        result[prefix + i] = ob[i];
      }
    }
  }
  return result;
}

/**
 * Bonus function to unflatten an object
 *
 * @param ob Object     The object to unflatten
 */
function unflattenObject(ob) {
  const result = {};
  for (const i in ob) {
    if (Object.prototype.hasOwnProperty.call(ob, i)) {
      const keys = i.match(/^\.+[^.]*|[^.]*\.+$|(?:\.{2,}|[^.])+(?:\.+$)?/g); // Just a complicated regex to only match a single dot in the middle of the string
      keys.reduce((r, e, j) => {
        return r[e] || (r[e] = isNaN(Number(keys[j + 1])) ? (keys.length - 1 === j ? ob[i] : {}) : []);
      }, result);
    }
  }
  return result;
}


// TESTS
const obj = {
  value: {
    foo: {
      bar: 'yes',
      so: {
        freakin: {
          nested: 'Wow',
        }
      }
    },
  },
  // Some edge cases to test
  test: [true, false, [null, undefined, 1]],
  not_lost: [], // Empty arrays should be preserved
  not_lost2: {}, // Empty objects should be preserved
  // Be careful with object having dots in the keys
  'I.like.dots..in.object.keys...': "... Please don't override me",
  I: {
    like: {
      'dots..in': {
        object: {
          'keys...': "You've been overwritten"
        }
      }
    }
  }
};
console.log(flattenObject(['I', {'am': 'an array'}]));
let flat = flattenObject(obj);
console.log(flat, unflattenObject(flat));
Run Code Online (Sandbox Code Playgroud)

如果您的对象包含带点的键,您可能会遇到一个明显的问题,以这种方式展平,这在小提琴中记录


Nin*_*olz 15

你可以只是连接所有的键和值.(它没有解决键的类型转换为数字.)

var object =  { 0: [1, 2, 3, 4] },
    result = Object.keys(object).reduce(function (r, k) {
        return r.concat(k, object[k]);
    }, []);
    
console.log(result);
Run Code Online (Sandbox Code Playgroud)

  • 如果您不希望将对象键添加到数组中,只需从.concat()中删除k即可。例如:`Object.keys(object).reduce(function(r,k){return r.concat(object [k]);},[]);` (2认同)

hus*_*ayt 10

我需要一些非常简单的东西,这是我想出的一个单线:

function flatten(obj){
  return Object.values(obj).flat()
}
Run Code Online (Sandbox Code Playgroud)

显然,这取决于您的浏览器/JS 环境是否支持这种语法。这是一个工作示例。

function flatten(obj){
  return Object.values(obj).flat()
}
Run Code Online (Sandbox Code Playgroud)

  • Array.prototype.flat 现在在所有主要浏览器中都受支持 (2认同)

gku*_*unz 9

简单对象到平面属性映射转换器的更现代的 JavaScript 和 TypeScript 实现。它使用 Object.entries 仅对拥有的属性执行适当的 for of 循环。

输入示例:

const address = {
  name: 'Address 1',
  address: {
    street: {name: 'Test Street', no: 123}
  }
};
Run Code Online (Sandbox Code Playgroud)

输出:

{
    'address.street.name': 'Test Street'
    'address.street.no': 123
    'name': 'Address 1'
}
Run Code Online (Sandbox Code Playgroud)

JavaScript:

export function toFlatPropertyMap(obj, keySeparator = '.') {
  const flattenRecursive = (obj, parentProperty, propertyMap = {}) => {
    for(const [key, value] of Object.entries(obj)){
      const property = parentProperty ? `${parentProperty}${keySeparator}${key}` : key;
      if(value && typeof value === 'object'){
        flattenRecursive(value, property, propertyMap);
      } else {
        propertyMap[property] = value;
      }
    }
    return propertyMap;
  };
  return flattenRecursive(obj);
}
Run Code Online (Sandbox Code Playgroud)

打字稿:

export function toFlatPropertyMap(obj: object, keySeparator = '.') {
  const flattenRecursive = (obj: object, parentProperty?: string, propertyMap: Record<string, unknown> = {}) => {
    for(const [key, value] of Object.entries(obj)){
      const property = parentProperty ? `${parentProperty}${keySeparator}${key}` : key;
      if(value && typeof value === 'object'){
        flattenRecursive(value, property, propertyMap);
      } else {
        propertyMap[property] = value;
      }
    }
    return propertyMap;
  };
  return flattenRecursive(obj);
}
Run Code Online (Sandbox Code Playgroud)


小智 8

Flattening Object can be done using recursion as below :

Sample Input

  let obj = {
    name: "test",
    address: {
    personal: "abc", 
    office: {
       building : 'random'
       street : 'some street',
    }
    }
}
Run Code Online (Sandbox Code Playgroud)

Expected Output

{
    name : "test",
    address_personal: "abc"
    address_office_building: "random"
    address_office_street: "some street"
}


Run Code Online (Sandbox Code Playgroud)

My Solution

  function flattenObj(obj, parent, res = {}){
    for(let key in obj){
        let propName = parent ? parent + '_' + key : key;
        if(typeof obj[key] == 'object'){
            flattenObj(obj[key], propName, res);
        } else {
            res[propName] = obj[key];
        }
    }
    return res;
}
Run Code Online (Sandbox Code Playgroud)

Hope it helps

  • `obj[key] == 'object'` 对于数组也是如此 (2认同)
  • 也许 `typeof obj[key] === typeof {} &amp;&amp; !Array.isArray(obj[key])` 会很好❤ (2认同)

Ale*_*lex 5

如果你真的很懒惰,那么你可以使用流行的 NPM 库flat

示例(来自他们的文档)

var flatten = require('flat')

flatten({
    key1: {
        keyA: 'valueI'
    },
    key2: {
        keyB: 'valueII'
    },
    key3: { a: { b: { c: 2 } } }
})

// {
//   'key1.keyA': 'valueI',
//   'key2.keyB': 'valueII',
//   'key3.a.b.c': 2
// }
Run Code Online (Sandbox Code Playgroud)