0

I have a very weird task to complete. Basically I have object like this:

{
   a: 'abc',
   key1: 'someKeyOne',
   key2: 'someKeyTwo',
   value1: 'someValueOne',
   value2: 'someValueTwo',
   yetAnotherProperty: 'dadjsa'
}

My goal is to create new object from properties that are keys and values so the new one will be:

{
  someKeyOne: 'someValueOne',
  someKeyTwo: 'someValueTwo',
}

In object there can be many "non key" or "non value" properties, but keyX and valueX are always in the same amount. I tried to use Object.keys and check if key includes key, and then value but I couldn't create new object from it...

Any advice?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
heisenberg7584
  • 563
  • 2
  • 10
  • 30

1 Answers1

2

You can use Object.entries to get the key/value pairs of your original object. Filter the ones where the key is like "keyX" (using a regex), and fetch the corresponding "valueX" value from the object. Map the key/value pair to this new pair. Finally create an object from these pairs with Object.fromEntries:

let obj = {a: 'abc',key1: 'someKeyOne',key2: 'someKeyTwo',value1: 'someValueOne',value2: 'someValueTwo',yetAnotherProperty: 'dadjsa'};

let result = Object.fromEntries(
    Object.entries(obj).filter(([k]) => /^key\d+$/.test(k))
                       .map(([k, v]) => [v, obj["value" + k.slice(3)]])
);

console.log(result);

In case you don't have support for Object.fromEntries, you can use Object.assign, which you can feed with one argument per new pair. In this case such a pair must be represented as a (little) object having just that one key:

let obj = {a: 'abc',key1: 'someKeyOne',key2: 'someKeyTwo',value1: 'someValueOne',value2: 'someValueTwo',yetAnotherProperty: 'dadjsa'};

let result = Object.assign({}, 
    ...Object.entries(obj).filter(([k]) => /^key\d+$/.test(k))
                          .map(([k, v]) => ({ [v]: obj["value" + k.slice(3)] }))
);

console.log(result);

To do the reverse, do as follows:

let obj = { someKeyOne: 'someValueOne', someKeyTwo: 'someValueTwo'};

let result = Object.fromEntries( 
    Object.entries(obj).flatMap(([k, v], i) => 
        [[`key${i+1}`, k], [`value${i+1}`, v]]
    )
);

console.log(result);

And the same with Object.assign instead of Object.fromEntries:

let obj = { someKeyOne: 'someValueOne', someKeyTwo: 'someValueTwo'};

let result = Object.assign({},
    ...Object.entries(obj).map(([k, v], i) => ({ 
        ["key" + (i+1)]: k, 
        ["value" + (i+1)]: v
    }))
);

console.log(result);
trincot
  • 317,000
  • 35
  • 244
  • 286
  • unfortunately I can't use Object.fromEntries because of ES version in project :( – heisenberg7584 Sep 30 '20 at 18:47
  • See addition to my answer. – trincot Sep 30 '20 at 19:06
  • aaand last one, Im so sorry! What if we want to reverse the process? So we have our object and want to have it back with form key1, value1, key2 etc... – heisenberg7584 Sep 30 '20 at 20:02
  • You should not ask follow up questions. You should first try, and when you cannot make it happen, ask a proper new question about it, showing your attempt. But OK, I added a snippet for it to this answer. You owe me. ;-) – trincot Sep 30 '20 at 20:11
  • so sorry @trincot, just trying to somehow use spread syntax inside the last one within `Object.assign({}, ....` is it possible? It may be shorter and clearer I guess – heisenberg7584 Oct 12 '20 at 16:48
  • There is already this spread syntax there. If you have a new question, please use the "Ask Question" button. – trincot Oct 12 '20 at 16:51
  • This is a follow up for your answer. I mean to use Object.fromEntries instead of Object.assign. I did it like this but there are some errors; " Object.fromEntries( Object.entries(obj).map(([k, v], i) => ({ [`key${i}`]: k, [`value${i}`]: v, })), ); " – heisenberg7584 Oct 13 '20 at 08:46
  • Sure, there are many ways to do this. – trincot Oct 13 '20 at 08:53
  • could you please provide some feedback for Object.fromEntries( Object.entries(obj).map(([k, v], i) => ({ [key${i}]: k, [value${i}]: v, })), ); ? It looks like the proper way but there is some error – heisenberg7584 Oct 13 '20 at 08:56
  • Wow just a mistake, sorry, I was sure I did it – heisenberg7584 Oct 13 '20 at 09:01
  • I am rereading my answer, ... and I see I did provide the solution with using `Object.fromEntries` too in the very first snippet. I see in your comment you don't filter anymore. I don't really understand what you are looking for here. – trincot Oct 13 '20 at 09:06
  • I am trying to use Object.fromEntries within this answer: `To do the reverse, do as follows:` - so to reverse the object to form key1: 'value' etc. – heisenberg7584 Oct 13 '20 at 09:08
  • OK, but `Object.fromEntries` expects an array of *pairs*, not of plain objects. I added the code for it to my answer (one-but-last snippet). – trincot Oct 13 '20 at 09:14