[英]What's the best way to turn all the keys of an nested array of objects to a camel case?
[英]What's the best way (most efficient) to turn all the keys of an object to lower case?
我想出了
function keysToLowerCase (obj) {
var keys = Object.keys(obj);
var n = keys.length;
while (n--) {
var key = keys[n]; // "cache" it, for less lookups to the array
if (key !== key.toLowerCase()) { // might already be in its lower case version
obj[key.toLowerCase()] = obj[key] // swap the value to a new lower case key
delete obj[key] // delete the old key
}
}
return (obj);
}
但是我不确定 v8 会如何处理它,例如,它真的会删除其他键还是只会删除引用并且垃圾收集器稍后会咬我?
另外,我创建了这些测试,我希望你可以在那里添加你的答案,这样我们就可以看到它们是如何匹配的。
编辑1:显然,根据测试,如果我们不检查密钥是否已经是小写字母,但速度更快,它会通过忽略这一点并创建新的小写密钥而造成更多混乱吗? 垃圾收集器会对此感到满意吗?
我想出的最快的方法是创建一个新对象:
var key, keys = Object.keys(obj);
var n = keys.length;
var newobj={}
while (n--) {
key = keys[n];
newobj[key.toLowerCase()] = obj[key];
}
我对 v8 当前的内部工作不够熟悉,无法给你一个明确的答案。 几年前我看到一个视频,开发人员谈论对象,而 IIRC 只会删除引用并让垃圾收集器处理它。 不过那是几年前的事了,就算那时候是那样,现在也不必那样了。
以后会咬你吗? 这取决于你在做什么,但可能不是。 创建短期对象是很常见的,因此代码被优化以处理它。 但每个环境都有其局限性,也许它会咬你。 您必须使用实际数据进行测试。
我会像这样使用Lo-Dash.transform :
var lowerObj = _.transform(obj, function (result, val, key) {
result[key.toLowerCase()] = val;
});
就个人而言,我会使用:
let objectKeysToLowerCase = function (origObj) {
return Object.keys(origObj).reduce(function (newObj, key) {
let val = origObj[key];
let newVal = (typeof val === 'object') ? objectKeysToLowerCase(val) : val;
newObj[key.toLowerCase()] = newVal;
return newObj;
}, {});
}
它简洁,递归处理嵌套对象并返回一个新对象而不是修改原始对象。
在我有限的本地测试中,此函数比当前列出的其他递归解决方案(一旦修复)更快。 我很想将它与其他人进行基准测试,但目前 jsperf 已关闭 (???)。
它也是用 ES5.1 编写的,因此,根据 MDN 上的文档,它应该适用于 FF 4+、Chrome 5+、IE 9.0+、Opera 12+、Safari 5+(所以,几乎所有的东西)。
Vanilla JS 获胜。
我不会太担心这一切的垃圾收集方面。 一旦对旧对象的所有引用都被销毁,它将是 GC,但新对象基本上仍将引用它的所有属性,因此它们不会。
任何函数、数组或正则表达式都将通过引用“复制”。 在内存方面,即使字符串也不会被这个过程复制,因为大多数(全部?)现代 JS 引擎用户字符串实习。 我认为只剩下构成原始结构的数字、布尔值和对象需要 GC 处理。
请注意,如果原始文件具有多个具有相同小写表示的属性,则此过程(的所有实现)将丢失值。 IE:
let myObj = { xx: 'There', xX: 'can be', Xx: 'only', XX: 'one!' };
console.log(myObj);
// { xx: 'There', xX: 'can be', Xx: 'only', XX: 'one!' }
let newObj = objectKeysToLowerCase(myObj);
console.log(newObj);
// { xx: 'one!' }
当然,有时这正是您想要的。
更新 2018-07-17
一些人注意到原始函数不适用于数组。 这是一个扩展的、更具弹性的版本。 如果初始值是数组或简单值,它会通过数组正确递归并工作:
let objectKeysToLowerCase = function (input) {
if (typeof input !== 'object') return input;
if (Array.isArray(input)) return input.map(objectKeysToLowerCase);
return Object.keys(input).reduce(function (newObj, key) {
let val = input[key];
let newVal = (typeof val === 'object') && val !== null ? objectKeysToLowerCase(val) : val;
newObj[key.toLowerCase()] = newVal;
return newObj;
}, {});
};
Object.fromEntries
(ES10) 使用新的Object.fromEntries
方法的本机和不可变解决方案:
const newObj = Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k.toLowerCase(), v])
);
在该功能广泛可用之前,您可以使用以下polyfill自己定义它:
Object.fromEntries = arr => Object.assign({}, ...Array.from(arr, ([k, v]) => ({[k]: v}) ));
一件好事是这个方法与Object.entries
做相反的事情,所以现在你可以在对象和数组表示之间来回切换。
ES6版本:
Object.keys(source)
.reduce((destination, key) => {
destination[key.toLowerCase()] = source[key];
return destination;
}, {});
loDash/fp 方式,非常好,因为它本质上是一个单衬
import {
mapKeys
} from 'lodash/fp'
export function lowerCaseObjectKeys (value) {
return mapKeys(k => k.toLowerCase(), value)
}
在我的测试中使用 forEach 似乎要快一些 - 并且原始参考已经消失,因此删除新参考将使 gc 可以使用它
function keysToLowerCase(obj){
Object.keys(obj).forEach(function (key) {
var k = key.toLowerCase();
if (k !== key) {
obj[k] = obj[key];
delete obj[key];
}
});
return (obj);
}
var O={一:1,二:2,三:3,四:4,五:5,六:{a:1,b:2,c:3,D:4,E:5}}; keysToLowerCase(O);
/* 返回值:(对象)*/
{
five:5,
four:4,
one:1,
six:{
a:1,
b:2,
c:3,
D:4,
E:5
},
three:3,
two:2
}
这是将所有 json 键转换为小写的最简单解决方案。
let o = {"Account_Number ":"0102301", "customer_NaME":"name"}
o = Object.keys(o).reduce((c, k) => (c[k.toLowerCase().trim()] = o[k], c), {})
console.log(o)
我使用了 ES6 和 TypeScript。 toLowerCaseObject
函数将一个数组作为参数,并递归地查看对象树并使每个节点小写:
function toLowerCaseObject(items: any[]) {
return items.map(x => {
let lowerCasedObject = {}
for (let i in x) {
if (x.hasOwnProperty(i)) {
lowerCased[i.toLowerCase()] = x[i] instanceof Array ? toLowerCaseObject(x[i]) : x[i];
}
}
return lowerCasedObject;
});
}
对于简单的情况,您可以使用以下示例将所有键转换为小写:
Object.keys(example).forEach(key => {
const value = example[key];
delete example[key];
example[key.toLowerCase()] = value;
});
您可以使用toUpperCase()
而不是toLowerCase()
将所有键转换为大写:
Object.keys(example).forEach(key => {
const value = example[key];
delete example[key];
example[key.toUpperCase()] = value;
});
单行(仅适用于顶级键):
Object.assign(...Object.keys(obj).map(key => ({[key.toLowerCase()]: obj[key]})))
转换:
{ a: 1, B: 2, C: { Z: 4 } }
到:
{ a: 1, b: 2, c: { Z: 4 } }
这不是最干净的方法,但它对我的团队有用,因此值得分享。
我创建了这个方法,因为我们的后端正在运行一种不区分大小写的语言,并且数据库和后端将产生不同的关键案例。 对我们来说,它完美无缺。 请注意,我们将日期作为字符串发送,我们不发送函数。
我们已将其缩减为这一行。
const toLowerCase = (data) => JSON.parse(JSON.stringify(data).replace(/"([^"]+)":/g, ($0, key) => '"' + key.toString().toLowerCase() + '":'))
我们使用JSON.parse(JSON.stringify(obj))
方法克隆对象。 这会以 JSON 格式生成对象的字符串版本。 虽然对象是字符串形式,但您可以使用正则表达式,因为 JSON 是一种可预测的格式来转换所有键。
拆开看是这个样子。
const toLowerCase = function (data) {
return JSON.parse(JSON.stringify(data)
.replace(/"([^"]+)":/g, ($0, key) => {
return '"' + key.toString().toLowerCase() + '":'
}))
}
const keysToLowerCase = object => {
return Object.keys(object).reduce((acc, key) => {
let val = object[key];
if (typeof val === 'object') {
val = keysToLowerCase(val);
}
acc[key.toLowerCase()] = val;
return acc;
}, {});
};
适用于嵌套对象。
使用打字稿
/**
* Lowercase the keys of an object
* @example
lowercaseKeys({FOO: true, bAr: false}); // {foo: true, bar: false}
*/
export function lowercaseKeys<T>(object: { [key: string]: T }): { [key: string]: T } {
const result: { [key: string]: T } = {};
for (const [key, value] of Object.entries(object)) {
result[key.toLowerCase()] = value;
}
return result;
}
用法
lowercaseKeys({FOO: true, bAr: false}); // {foo: true, bar: false}
考虑一次降低大小写,将其存储在一个lowKey
:
function keysToLowerCase (obj) {
var keys = Object.keys(obj);
var n = keys.length;
var lowKey;
while (n--) {
var key = keys[n];
if (key === (lowKey = key.toLowerCase()))
continue
obj[lowKey] = obj[key]
delete obj[key]
}
return (obj);
}
这是我基于上述示例之一的递归版本。
//updated function var lowerObjKeys = function(obj) { Object.keys(obj).forEach(function(key) { var k = key.toLowerCase(); if (k != key) { var v = obj[key] obj[k] = v; delete obj[key]; if (typeof v == 'object') { lowerObjKeys(v); } } }); return obj; } //plumbing console = { _createConsole: function() { var pre = document.createElement('pre'); pre.setAttribute('id', 'console'); document.body.insertBefore(pre, document.body.firstChild); return pre; }, info: function(message) { var pre = document.getElementById("console") || console._createConsole(); pre.textContent += ['>', message, '\\n'].join(' '); } }; //test case console.info(JSON.stringify(lowerObjKeys({ "StackOverflow": "blah", "Test": { "LULZ": "MEH" } }), true));
请注意,它不跟踪循环引用,因此您最终可能会遇到导致堆栈溢出的无限循环。
对于所有值:
to_lower_case = function(obj) {
for (var k in obj){
if (typeof obj[k] == "object" && obj[k] !== null)
to_lower_case(obj[k]);
else if(typeof obj[k] == "string") {
obj[k] = obj[k].toLowerCase();
}
}
return obj;
}
同样可用于稍作调整的键。
我就是这样做的。 我的输入可以是任何东西,它通过嵌套对象以及对象数组回避。
const fixKeys = input => Array.isArray(input)
? input.map(fixKeys)
: typeof input === 'object'
? Object.keys(input).reduce((acc, elem) => {
acc[elem.toLowerCase()] = fixKeys(input[elem])
return acc
}, {})
: input
使用 mocha 测试
const { expect } = require('chai')
const fixKeys = require('../../../src/utils/fixKeys')
describe('utils/fixKeys', () => {
const original = {
Some: 'data',
With: {
Nested: 'data'
},
And: [
'an',
'array',
'of',
'strings'
],
AsWellAs: [
{ An: 'array of objects' }
]
}
const expected = {
some: 'data',
with: {
nested: 'data'
},
and: [
'an',
'array',
'of',
'strings'
],
aswellas: [{ an: 'array of objects' }]
}
let result
before(() => {
result = fixKeys(original)
})
it('left the original untouched', () => {
expect(original).not.to.deep.equal(expected)
})
it('fixed the keys', () => {
expect(result).to.deep.equal(expected)
})
})
var aa = {ID:1,NAME:'Guvaliour'};
var bb= {};
var cc = Object.keys(aa);
cc.forEach(element=>{
bb[element.toLowerCase()]=aa[element];
});
cosole.log(bb)
以下代码将所有键转换为小写
array.forEach(item=>{
let data = Object.keys(item).reduce((result, p) => (result[p.toLowerCase().trim()] = item[p], result), {})
if(data.hasOwnProperty(fieldname)){
if(data[fieldname]){
if(!response['data'].includes(data[fieldname].toLowerCase()))
response['data'].push(data[fieldname])
}
}
})
虽然 ES10 Object.fromentries() 方法有效
const newObj = Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k.toLowerCase(), v])
);
您可以类似地将下面的代码片段用于 ES2015 及以下版本
this.htmlWorkbookJSON = jsonData.map((element: Object) => {
let entriesArray = Object.entries(element)
const data = new Object()
entriesArray.forEach(([key, value]) => {
data[key.toLocaleLowerCase()] = value;
})
return data
})
const objectToLowercase = (data) => { return Object.keys(data).reduce((toLowerKeyObj, key) => { toLowerKeyObj[key.toLowerCase()] = typeof data[key] === 'object'? objectToLowercase(data[key]): data[key]; return toLowerKeyObj; }, {}); }; console.log(objectToLowercase({"NAME":"Recep", "JOB": { "NAME":"Fullstack Dev." } }))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.