how to change a value in an array of objects [duplicate] - javascript
This question already has answers here:
How to change value of object which is inside an array using JavaScript or jQuery?
(34 answers)
Closed 2 years ago.
I have this array of objects:
const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
and am trying to figure out how to change the value in a given object in this original array (do not want to make a copy of the array). I have tried this
index = 4;
indexStates.filter(o => o[index] = !o[index]);
console.log(indexStates);
but the result is
[{"4": false}, {"3": false, "4": true}, {"4": true, "7": false}, {"1": true, "4": true}]
instead of changing the value only in {"4": false} and leaving the other objects as is. What am I doing wrong? Also, I don't want to use third party libraries for this operation.
Few comments for your code:
index = 4;
indexStates.filter(o => o[index] = !o[index]);
this 'index' should be a property name, not a position in the array, and with o[index] = !o[index] its a assignment, not a predicate
Instead, Try this
var indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
var index = 4;
var toChange = indexStates.filter(o => Object.getOwnPropertyNames(o).filter(n => n == index)[0] !== undefined)[0];
toChange[index] = !toChange[index]
console.log(toChange);
console.log(indexStates);
What you are basically saying is:
filter this array to bring you only the items that the following action:
index "4" should be assigned with the opposite value
results into true, which means that the items that do not have index 4 (meaning its false in js) will be updated too.
What you need to do is:
console.log(indexStates.map(o => o[index] !== undefined ? {[index]: !o[index]} : o))
which will return a new array for you to use.
If you do not want to create a copy, you should go for for loop and check if the key/object exists int the current object and verify. If the value is there then negate it. Below is the snippet for the same. Hope this helps
const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
index = "4";
const length = indexStates.length;
for(let i =0; i< length; i++) {
let elem = indexStates[i];
if(elem[index]) elem[index] = !elem[index]
}
console.log(indexStates);
If you can't make a copy of the array... then you could do this:
const getIndexOfTarget = (states, target) => {
const value = states.find(state => Object.keys(state)[0] === target)
return states.indexOf(value)
}
const states = [{"4": true}, {"3": false}, {"7": false}, {"1": true}];
const target = String(4)
const itemToChange = getIndexOfTarget(states, target)
states[itemToChange][target] = false // or !states[itemToChange][target]
Note I cast the index, or in this case target, to a String because that's what the key types are in the objects (you could just put "4" if you own it).
If you're going to have multiple "index" of the same value, then you'd need to swap the find with a filter.
const getIndexesOfTarget = (states, target) => {
const values = states.filter(state => Object.keys(state)[0] === target)
return values.map(val => states.indexOf(value))
}
const itemsToChange = getIndexesOfTarget(states, target)
itemsToChange.forEach(item => states[item][target] = !states[item][target])
I would go with a foreach approach
const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
indexStates.forEach(elem => {
if(typeof elem[index] === 'undefined') return elem;
elem[index] = !elem[index];
return elem;
}
How about forEach. You can do it like this, if I understand your question correctly:
var indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
var target = '4';
indexStates.forEach(val=>{
if(Object.keys(val).includes(target)) val[target]=!val[target];
});
console.log(indexStates);
Related
Insert all properties from an object within an array to another object in array using JS/TS
I have been looking a simple way to copy/insert/move properties in an object within an array to another object. I came up with a basic logic which does the job perfectly but am not satisfied with this. There has to be a better way, any help here? var first = [ { "AGREE_EFF_DATE__0": "02-Aug-2018", "AGREE_TERM_DATE__0": "30-Apr-2021", "AGREE_IND__0": "P1", "P_DBAR_IND__0": "N", "AGREE_EFF_DATE__1": "01-May-2021", "AGREE_TERM_DATE__1": null, "AGREE_IND__1": "NP", "P_DBAR_IND__1": "N", "PROVIDER_SPECIALITY__0": "PSYCHOLOGY, CLINICAL", "PROVIDER_SPECIALITY_CODE__0": "CK" } ]; var second = [ { "STATUS": "ACTIVE", "MEDICARE_NUMBER" : 12345 } ]; for(let i = 0; i < second.length; i++) { var first_keys = Object.keys(first[i]); var first_values = Object.values(first[i]); for(let j = 0; j < first_keys.length; j++) { second[i][first_keys[j]] = first_values[j]; } } console.log(second); //Output- [ { STATUS: 'ACTIVE', MEDICARE_NUMBER: 12345, AGREE_EFF_DATE__0: '02-Aug-2018', AGREE_TERM_DATE__0: '30-Apr-2021', AGREE_IND__0: 'P1', P_DBAR_IND__0: 'N', AGREE_EFF_DATE__1: '01-May-2021', AGREE_TERM_DATE__1: null, AGREE_IND__1: 'NP', P_DBAR_IND__1: 'N', PROVIDER_SPECIALITY__0: 'PSYCHOLOGY, CLINICAL', PROVIDER_SPECIALITY_CODE__0: 'CK' } ]
When possible, you should prefer iteration to manually indexed loops. This means arr.map() or arr.forEach() or arr.reduce(), to name a few. Also, You can use an object spread to easily merge objects together. Putting those together, you can reduce this logic to: const result = first.map((firstObj, i) => ({ ...firstObj, ...second[i] })) Here we map() over all members of first, which returns a new array where each member is the result of the function. This function takes the array member as the first argument, and the index of that member as the second argument. Then we can use that index to find the corresponding item in the second array. Then you just spread both objects into a new object to assemble the final result. var first = [ { a: 1, b: 2 }, { a: 4, b: 5 }, ]; var second = [ { c: 3 }, { c: 6 }, ]; const result = first.map((firstObj, i) => ({ ...firstObj, ...second[i] })) console.log(result) Which is all perfectly valid typescript as well. NOTE: there is one difference between my code any yours. Your code modifies the objects in second. My code returns new objects and does not change the contents of second at all. This is usually the better choice, but it depends on how you use this value and how data is expected to flow around your program.
You need to be careful with iterating, because you can have different count of elements in first and second arrays. So the possible solution will be like this: const first = [ { "AGREE_EFF_DATE__0": "02-Aug-2018", "AGREE_TERM_DATE__0": "30-Apr-2021", "AGREE_IND__0": "P1", "P_DBAR_IND__0": "N", "AGREE_EFF_DATE__1": "01-May-2021", "AGREE_TERM_DATE__1": null, "AGREE_IND__1": "NP", "P_DBAR_IND__1": "N", "PROVIDER_SPECIALITY__0": "PSYCHOLOGY, CLINICAL", "PROVIDER_SPECIALITY_CODE__0": "CK" } ]; const second = [ { "STATUS": "ACTIVE", "MEDICARE_NUMBER": 12345 } ]; console.log(mergeAll(first, second)); function mergeAll(firstArray, secondArray) { const result = []; const minLength = firstArray.length < secondArray.length ? firstArray.length : secondArray.length; for (let i = 0; i < minLength; i++) { result.push({...firstArray[i], ...secondArray[i]}); } return result; }
How to swap keys and values in an object? JS
Please tell me how to get such an array where id : newExcluded(key), and excluded :(newExcluded value ) const newExcluded = {1:true,6:false,3:false,4:true,7:true} coonst fetchExcluded = [ {"id": 1,"excluded": true}, {"id": 6, "excluded": false}, {"id": 3, "excluded": false}, {"id": 4, "excluded": true}, {"id": 7, "excluded": true}, ]
You can use a Object.entries to convert it to an array of arrays and Array.prototype.map to convert each inner array to an object with the required properties const newExcluded = {1:true,6:false,3:false,4:true,7:true} fetchExcluded = Object.entries(newExcluded).map(([id, excluded]) => ({ id, excluded })); console.log(fetchExcluded);
Without using map. Iterate over the Object.entries (this returns an array which is why we're using for/of), and assign the key/value of each property to a new object. const obj = {1:true,6:false,3:false,4:true,7:true}; const output = {}; for (const [key, value] of Object.entries(obj)) { output[key] = value; } console.log(output);
How extract Object with "{ }" from an string [duplicate]
This question already has answers here: Check if a value is an object in JavaScript (54 answers) Closed 3 years ago. I try to extract Object from bellow array : var array = []; array = a,b,c,{"A":"0","f":"1","g":"2"},{"B":"5","v":"8","x":"4"},{"C":"0","f":"1","g":"2"},c,b imagine extract this : result = [ {"A":"0","f":"1","g":"2"},{"B":"5","v":"8","x":"4"},{"C":"0","f":"1","g":"2"} ] I use my code but didn't give me the right answer : for (var i =0 ; i < array.length ; i++) { console.log((array[i].split(',')); } In this code I just get each variable in each line I need more thing because in each time maybe I have different array that has for example 2 Object in this example I just have 3 Object.I try to define If I has any Object I can find them and push them in one array.
You can use Array.filter var array = []; array = [ 'a','b','c',{"A":"0","f":"1","g":"2"},{"B":"5","v":"8","x":"4"},{"C":"0","f":"1","g":"2"},'c','b' ]; let result = array.filter(e => typeof e === 'object'); console.log(result)
You can use array reduce function. Inside reduce callback check if the type of the element is object then in accumulator array push the element var array = []; array = [ 'a', 'b', 'c', { "A": "0", "f": "1", "g": "2" }, { "B": "5", "v": "8", "x": "4" }, { "C": "0", "f": "1", "g": "2" }, 'c', 'b' ]; let newArr = array.reduce((acc, curr) => { if (typeof(curr) === 'object') { acc.push(curr) } return acc; }, []); console.log(newArr)
Getting object property value
My array is the following: let arr = [ {type: "Benzine", active: false}, {type: "Diesel", active: false}, {type: "Electricity", active: false} ] And I have a function where I want to get value of the property active of that array: function isChecked(filterName) { return arr.filter(f => f.type === filterName).map(c => c.active)[0]; } That works fine, with [0] at the end. Is there any way to show the active property value without [0] at the end?
No, as long as you use filter, there's not. The [0] is used to get the first result from that filter. Since you're just returning the value of active, you could use Array.prototype.some, instead: let arr = [ {type: "Benzine", active: false}, {type: "Diesel", active: false}, {type: "Electricity", active: true} ]; function isChecked(filterName){ // Is there an element in the array that matches the filter AND is active? return arr.some(f => f.type === filterName && f.active); } console.log("Diesel:", isChecked("Diesel")); console.log("Electricity:", isChecked("Electricity"));
Instead of using filter, you can use find to get the first matching element of an array. function isChecked(filterName) { var elem = arr.find(f => f.type === filterName); return elem ? elem.active : false; }
How to convert an Object {} to an Array [] of key-value pairs in JavaScript
I want to convert an object like this: {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0} into an array of key-value pairs like this: [[1,5],[2,7],[3,0],[4,0]...]. How can I convert an Object to an Array of key-value pairs in JavaScript?
You can use Object.keys() and map() to do this var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0} var result = Object.keys(obj).map((key) => [Number(key), obj[key]]); console.log(result);
The best way is to do: var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0} var result = Object.entries(obj); console.log(result); Calling entries, as shown here, will return [key, value] pairs, as the caller requested. Alternatively, you could call Object.values(obj), which would return only values.
Object.entries() returns an array whose elements are arrays corresponding to the enumerable property [key, value] pairs found directly upon object. The ordering of the properties is the same as that given by looping over the property values of the object manually. - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Description The Object.entries function returns almost the exact output you're asking for, except the keys are strings instead of numbers. const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; console.log(Object.entries(obj)); If you need the keys to be numbers, you could map the result to a new array with a callback function that replaces the key in each pair with a number coerced from it. const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; const toNumericPairs = input => { const entries = Object.entries(input); return entries.map(entry => Object.assign(entry, { 0: +entry[0] })); } console.log(toNumericPairs(obj)); I use an arrow function and Object.assign for the map callback in the example above so that I can keep it in one instruction by leveraging the fact that Object.assign returns the object being assigned to, and a single instruction arrow function's return value is the result of the instruction. This is equivalent to: entry => { entry[0] = +entry[0]; return entry; } As mentioned by #TravisClarke in the comments, the map function could be shortened to: entry => [ +entry[0], entry[1] ] However, that would create a new array for each key-value pair, instead of modifying the existing array in place, hence doubling the amount of key-value pair arrays created. While the original entries array is still accessible, it and its entries will not be garbage collected. Now, even though using our in-place method still uses two arrays that hold the key-value pairs (the input and the output arrays), the total number of arrays only changes by one. The input and output arrays aren't actually filled with arrays, but rather references to arrays and those references take up a negligible amount of space in memory. Modifying each key-value pair in-place results in a negligible amount of memory growth, but requires typing a few more characters. Creating a new array for each key-value pair results in doubling the amount of memory required, but requires typing a few less characters. You could go one step further and eliminate growth altogether by modifying the entries array in-place instead of mapping it to a new array: const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; const toNumericPairs = input => { const entries = Object.entries(obj); entries.forEach(entry => entry[0] = +entry[0]); return entries; } console.log(toNumericPairs(obj));
To recap some of these answers now on 2018, where ES6 is the standard. Starting with the object: let const={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5}; Just blindly getting the values on an array, do not care of the keys: const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5}; console.log(Object.values(obj)); //[9,8,7,6,5,4,3,2,1,0,5] Simple getting the pairs on an array: const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5}; console.log(Object.entries(obj)); //[["1",9],["2",8],["3",7],["4",6],["5",5],["6",4],["7",3],["8",2],["9",1],["10",0],["12",5]] Same as previous, but with numeric keys on each pair: const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5}; console.log(Object.entries(obj).map(([k,v])=>[+k,v])); //[[1,9],[2,8],[3,7],[4,6],[5,5],[6,4],[7,3],[8,2],[9,1],[10,0],[12,5]] Using the object property as key for a new array (could create sparse arrays): const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5}; console.log(Object.entries(obj).reduce((ini,[k,v])=>(ini[k]=v,ini),[])); //[undefined,9,8,7,6,5,4,3,2,1,0,undefined,5] This last method, it could also reorganize the array order depending the value of keys. Sometimes this could be the desired behaviour (sometimes don't). But the advantage now is that the values are indexed on the correct array slot, essential and trivial to do searches on it. Map instead of Array Finally (not part of the original question, but for completeness), if you need to easy search using the key or the value, but you don't want sparse arrays, no duplicates and no reordering without the need to convert to numeric keys (even can access very complex keys), then array (or object) is not what you need. I will recommend Map instead: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map let r=new Map(Object.entries(obj)); r.get("4"); //6 r.has(8); //true
In Ecmascript 6, var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; var res = Object.entries(obj); console.log(res); var obj = { "1": 5, "2": 7, "3": 0, "4": 0, "5": 0, "6": 0, "7": 0, "8": 0, "9": 0, "10": 0, "11": 0, "12": 0 }; var res = Object.entries(obj); console.log(res);
Yet another solution if Object.entries won't work for you. const obj = { '1': 29, '2': 42 }; const arr = Array.from(Object.keys(obj), k=>[`${k}`, obj[k]]); console.log(arr);
Use Object.keys and Array#map methods. var obj = { "1": 5, "2": 7, "3": 0, "4": 0, "5": 0, "6": 0, "7": 0, "8": 0, "9": 0, "10": 0, "11": 0, "12": 0 }; // get all object property names var res = Object.keys(obj) // iterate over them and generate the array .map(function(k) { // generate the array element return [+k, obj[k]]; }); console.log(res);
Use Object.entries to get each element of Object in key & value format, then map through them like this: var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0} var res = Object.entries(obj).map(([k, v]) => ([Number(k), v])); console.log(res); But, if you are certain that the keys will be in progressive order you can use Object.values and Array#map to do something like this: var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; // idx is the index, you can use any logic to increment it (starts from 0) let result = Object.values(obj).map((e, idx) => ([++idx, e])); console.log(result);
You can use Object.values([]), you might need this polyfill if you don't already: const objectToValuesPolyfill = (object) => { return Object.keys(object).map(key => object[key]); }; Object.values = Object.values || objectToValuesPolyfill; https://stackoverflow.com/a/54822153/846348 Then you can just do: var object = {1: 'hello', 2: 'world'}; var array = Object.values(object); Just remember that arrays in js can only use numerical keys so if you used something else in the object then those will become `0,1,2...x`` It can be useful to remove duplicates for example if you have a unique key. var obj = {}; object[uniqueKey] = '...';
With lodash, in addition to the answer provided above, you can also have the key in the output array. Without the object keys in the output array for: const array = _.values(obj); If obj is the following: { “art”: { id: 1, title: “aaaa” }, “fiction”: { id: 22, title: “7777”} } Then array will be: [ { id: 1, title: “aaaa” }, { id: 22, title: “7777” } ] With the object keys in the output array If you write instead ('genre' is a string that you choose): const array= _.map(obj, (val, id) => { return { ...val, genre: key }; }); You will get: [ { id: 1, title: “aaaa” , genre: “art”}, { id: 22, title: “7777”, genre: “fiction” } ]
If you are using lodash, it could be as simple as this: var arr = _.values(obj);
var obj = { "1": 5, "2": 7, "3": 0, "4": 0, "5": 0, "6": 0, "7": 0, "8": 0, "9": 0, "10": 0, "11": 0, "12": 0 } let objectKeys = Object.keys(obj); let answer = objectKeys.map(value => { return [value + ':' + obj[value]] });
const persons = { john: { age: 23, year:2010}, jack: { age: 22, year:2011}, jenny: { age: 21, year:2012} } const resultArray = Object.keys(persons).map(index => { let person = persons[index]; return person; }); //use this for not indexed object to change array
This is my solution, i have the same issue and its seems like this solution work for me. yourObj = [].concat(yourObj);
or you can use Object.assign(): const obj = { 0: 1, 1: 2, 2: 3}; const arr = Object.assign([], obj); console.log(arr) // arr is [1, 2, 3]
Here is a "new" way with es6 using the spread operator in conjunction with Object.entries. const data = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; const dataSpread = [...Object.entries(data)]; // data spread value is now: [ [ '1', 5 ], [ '2', 7 ], [ '3', 0 ], [ '4', 0 ], [ '5', 0 ], [ '6', 0 ], [ '7', 0 ], [ '8', 0 ], [ '9', 0 ], [ '10', 0 ], [ '11', 0 ], [ '12', 0 ] ]
you can use 3 methods convert object into array (reference for anyone not only for this question (3rd on is the most suitable,answer for this question) Object.keys() ,Object.values(),andObject.entries() examples for 3 methods use Object.keys() const text= { quote: 'hello world', author: 'unknown' }; const propertyNames = Object.keys(text); console.log(propertyNames); result [ 'quote', 'author' ] use Object.values() const propertyValues = Object.values(text); console.log(propertyValues); result [ 'Hello world', 'unknown' ] use Object.entires() const propertyValues = Object.entires(text); console.log(propertyValues); result [ [ 'quote', 'Hello world' ], [ 'author', 'unknown' ] ]
Use for in var obj = { "10":5, "2":7, "3":0, "4":0, "5":0, "6":0, "7":0, "8":0, "9":0, "10":0, "11":0, "12":0 }; var objectToArray = function(obj) { var _arr = []; for (var key in obj) { _arr.push([key, obj[key]]); } return _arr; } console.log(objectToArray(obj));
Recursive convert object to array function is_object(mixed_var) { if (mixed_var instanceof Array) { return false; } else { return (mixed_var !== null) && (typeof( mixed_var ) == 'object'); } } function objectToArray(obj) { var array = [], tempObject; for (var key in obj) { tempObject = obj[key]; if (is_object(obj[key])) { tempObject = objectToArray(obj[key]); } array[key] = tempObject; } return array; }
We can change Number to String type for Key like below: var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0} var result = Object.keys(obj).map(function(key) { return [String(key), obj[key]]; }); console.log(result);
you can use _.castArray(obj). example: _.castArray({ 'a': 1 }); // => [{ 'a': 1 }]