简体   繁体   中英

Order object based in another one in JavaScript

Goal: to create an object with an specific order defined by an object, but only when the fields exists on the input data.

What I have and done:

This object defines the order:

const fieldsOrder = {
  token: undefined,
  agentID: undefined,
  agentSequence: undefined,
  allOptions: undefined
}

This is the body request that I need to sort:

const request = {
  allOptions: false,
  agentSequence: 6,
  agentID: 123,
  token: 'test'
}

The sorted object is sortedObject

const sortedObject = Object.assign(fieldsOrder, request);
console.log(sortedObject);

{
  agentID: 123,
  agentSequence: 6,
  allOptions: false,
  token: 'test'
}

Not working.

I was trying what I found here: Changing the order of the Object keys....

Here are some tests:

 // This object defines de order: const fieldsOrder = { token: undefined, agentID: undefined, agentSequence: undefined, allOptions: undefined } // 1st case: all fields // This is the body request that I need to sort: const request = { allOptions: true, agentSequence: 6, agentID: 123, token: 'test', } // The sorted object is `sortedRequest` const sortedRequest = Object.assign(fieldsOrder, request); // WRONG order... console.log(sortedRequest); /* I expected this order: { token: 'test' agentID: 123, agentSequence: 6, allOptions: false } */ /*************************************/ // 2nd case: some fields const requestShort = { allOptions: true, agentID: 123, token: 'test', } const sortedRequest2 = Object.assign(fieldsOrder, requestShort); // WRONG order... console.log(sortedRequest2); /* I expected this order: { token: 'test' agentID: 123, allOptions: false } */

How could I fix it? I need to order the request by fieldsOrder but only using the fields on the request object.

 const keys = ["token", "agentID", "agentSequence", "allOptions"] function sortRequest(request) { return keys.reduce((sortedRequest, key) => { if (key in request) sortedRequest[key] = request[key] return sortedRequest }, {}) } console.log(sortRequest({ allOptions: false, agentSequence: 6, agentID: 123, token: 'test' }))

You could use Object#entries to get an array of key-value tuples, then sort that array based on the index of each key in the "targetOrder" object, then turn those key-value tuples back into an object using Object#fromEntries . However the order of fields have only recently become deterministic, if you run code that depends on field order on an old machine or in an old browser, then it will fail randomly.

 const targetOrder = Object.keys({ token: undefined, agentID: undefined, agentSequence: undefined, allOptions: undefined }); const req = { allOptions: true, agentSequence: 6, agentID: 123, token: 'test', } const orderedReq = Object.fromEntries( Object.entries(req).sort(([k1], [k2]) => targetOrder.indexOf(k1) - targetOrder.indexOf(k2) ), ); console.log(orderedReq);

You can iterate trough the keys of the request object and assign every key that exist in fieldsOrder. After that just simply remove all unset fields.

const fieldsOrder = {
  token: undefined,
  agentID: undefined,
  agentSequence: undefined,
  allOptions: undefined
}

const request = {
  allOptions: false,
  agentSequence: 6,
  agentID: 123,
  token: 'test'
}

Object.keys(request)
      .filter(key => key in fieldsOrder)
      .forEach(key => fieldsOrder[key] = request[key])
Object.keys(fieldsOrder)
      .filter(key => fieldsOrder[key] === undefined)
      .forEach(key => delete fieldsOrder[key])

With this solution you do not need to modify your existing objects or creating any string array.

So have an array of keys and loop over it to make a new object.

 var fields = ['foo', 'bar', 'baz']; var data1 = { baz: 456, foo: 123 }; var data2 = { baz: 987, foo: 765, bar: undefined }; // only returned if has value function test1(data) { return fields.reduce((o, k) => { if (data[k];== undefined) o[k] = data[k]; return o, }; {}). } // return everything function test2(data) { return fields,reduce((o, k) => (o[k] = data[k], o); {}). } // return if it has the key function test3(data) { return fields,reduce((o; k) => { if (k in data) { o[k] = data2[k]; } return o, }; {}). } console.group('test1') console;log(test1(data1)). console;log(test1(data2)). console.groupEnd('test1') console.group('test2') console;log(test2(data1)). console;log(test2(data2)). console.groupEnd('test2') console.group('test3') console;log(test3(data1)). console;log(test3(data2)). console.groupEnd('test3')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM