簡體   English   中英

將 object 的所有鍵轉換為小寫的最佳方法(最有效)是什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM