3

Hi I have below code in my project. The problem is the last item is being pushed to an array instead of each item.

JS Function


function getArrayObjForKeys(keys, source, desiredKeys) {
  let arrayObj = [],
    obj = {};
  source.forEach(function(val, ind) {
    keys.forEach(function(v, i) {
      (function(v) {
        if (val.hasOwnProperty(v)) {
          let desKey = desiredKeys[i];
          obj[desKey] = val[v];
        }
      }).call(this, v);
    });
    arrayObj.push(obj);
  });
  return arrayObj;
}

// Invoking function as below
// **************************

var source = [{
  'country': 'USA',
  'descr': 'United States'
}, {
  'country': 'UK',
  'descr': 'United Kingdom'
}];
var countryList = getArrayObjForKeys(['country', 'descr'], source, ['value', 'label']);
console.info(countryList);

Desired Output


[{'value':'USA','label':'United States'},{'value':'UK','label':'United Kingdom'}]

Plunker


https://next.plnkr.co/edit/3SKbaJo9r5QX8hex?open=lib%2Fscript.js

0

6 Answers 6

2

Your issue is that you're referring to the same obj in memory and thus modifying both objects. A quick fix to this is to move your object declaration into the foreach loop, so you have your own unique reference to each object (not the same).

See working example below:

function getArrayObjForKeys(keys, source, desiredKeys) {
  let arrayObj = []
  
  source.forEach(function(val, ind) {
    let obj = {}; /* Move into foreach */
    keys.forEach(function(v, i) {
      (function(v) {
        if (val.hasOwnProperty(v)) {
          let desKey = desiredKeys[i];
          obj[desKey] = val[v];
        }
      }).call(this, v);
    });
    arrayObj.push(obj);
  });
  return arrayObj;
}


var source = [{
  'country': 'USA',
  'descr': 'United States'
}, {
  'country': 'UK',
  'descr': 'United Kingdom'
}];

var countryList = getArrayObjForKeys(['country', 'descr'], source, ['value', 'label']);
console.info(countryList);

Sign up to request clarification or add additional context in comments.

1 Comment

@ukb awesome! no worries :)
1

You can map the source to the desired output using reduce to reduce the keys, desiredKeys and object to a new object:

function getArrayObjForKeys(keys, source, desiredKeys) {
    return source.map(function(obj) {
        return keys.reduce(function(result, key, index) {
            result[desiredKeys[index]] = obj[key];
            return result;
        }, {});
    });
}

var source = [{ country: 'USA', descr: 'United States' }, { country: 'UK', descr: 'United Kingdom' }];
var countryList = getArrayObjForKeys(['country', 'descr'], source, ['value', 'label']);
console.info(countryList);

Comments

0

Here is another way to do it, using reduce, Object.entries and map:

function getArrayObjForKeys(keys, source, desiredKeys) {
  return source.map(obj => Object.entries(obj).reduce((accum, [key, val]) => {
    const keyIdx = keys.indexOf(key);
    accum[desiredKeys[keyIdx]] = val;
    return accum;
  }, {}));
}

const source = [
  { 'country': 'USA', 'descr': 'United States' },
  { 'country': 'UK', 'descr': 'United Kingdom' }
];

const countryList = getArrayObjForKeys(['country', 'descr'], source, ['value', 'label']);

console.info(countryList);

2 Comments

Object.entries is not to be guaranteed to come in any particular order so you should not use it in this way.
Well, in this case it is not a problem since we are outputting an object from the reduce function, and keys are not guaranteed to be ordered in an object either. So the input is unordered, you are right, but the output does not rely on the input being ordered.
0

A more concise alternative, using ES6 (and provided both input arrays always have the same length) would be :

const getArrayObjForKeys = (keys, source, desiredKeys) => source.map( obj => {
	let output = {};
	keys.forEach( (key,i) => output[desiredKeys[i]] = obj[keys[i]]);
	return output;
})
 

const source = [{'country':'USA','descr':'United States'},{'country':'UK','descr':'United Kingdom'}],
	  countryList = getArrayObjForKeys(['country','descr'], source, ['value','label']);

console.info(countryList);

Comments

0
getArrayObjForKeys(keys,source,desiredKeys){
    let arrayObj=[];
    source.forEach(function(val,ind){
    let obj={};
        keys.forEach(function(v,i){
          (function(v){
            if(val.hasOwnProperty(v)){
              let desKey = desiredKeys[i];
              obj[desKey] = val[v];
            }
          }).call(this, v);
        });
        arrayObj.push(obj);
    });
    return arrayObj;
  }

Update the obj variable inside the foreach loop.

Issue is with obj variable

Comments

0

If you want less code, here's a more specific function.

function easy(obj) {
  return obj = obj.map(obj => {
    return {"value": obj.country, "lable": obj.descr};
  });
}

obj = [{
  "country": "USA",
  "descr": "United States"
}, {
  "country": "UK",
  "descr": "United Kingdom"
}];

obj = easy(obj);

console.log(obj);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.