Dynamically add a property with spread operator - javascript

Let's take 2 objects and let's say I want to dynamically add a key to the first object with the value of the second, and to do this I want to use the spread operator.
let object1 = { key: 'myKey1', value:1 };
let object2 = { field: 'key', displaValue:'chiave' };
something like this:
let object3 = {...object1, [object2.displayValue)]: object1[object2.field] }
But unfortunately I have this result with the undefined key:
{key: "myKey1", value: 1, undefined: "myKey1"}
Expected result:
{key: "myKey1", value: 1, chiave: "myKey1"}

Related

Filter and loop thru non-array flat JSON object in javascript [duplicate]

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 2 years ago.
I have the following JSON, which I use as some kind of enum equivalent for javascript:
const blah = {
IV: {
name: "dIV",
value: 1
},
III: {
name: "dIII",
value: 2
},
II: {
name: "dII",
value: 3
},
I: {
name: "dI",
value: 4
}
};
I would like to filter all the objects by value and then be able to loop through the result.
I tried to do something like:
let result = blah.find(x => x.value > 2);
result.each(function () {
console.log(this)
}
but this doesn't work and throws: blah.find is not a function.
The expected output would contain two elements:
II: { name: "dII", value: 3},
I: { name: "dI", value: 4}
Most of the examples I've found on the Internet use arrays in the JSON structure. Is there any option
to achieve what I want or I need to modify the JSON structure and use an array?
Cheers
You can iterate over your object (note, it is a javascript literal object, not a JSON) with a simple for...in that loops through each object key (enumerable properties), for me, this is the most controllable and readable way, but there is many more, as you would see in other people answers.
const blah = {IV: {name: "dIV", value: 1}, III: {name: "dIII", value: 2}, II: { name: "dII", value: 3}, I: {name: "dI", value: 4}};
let result = []
for (let key in blah){
let object = blah[key]
if (object.value > 2){
result.push(object)
}
}
console.log(result)
Another possibilty is using Object.values (that returns all values from an object into an array)
and an Array.filter (that the name says all), this is less code and more "elegant":
const blah = {IV: {name: "dIV", value: 1}, III: {name: "dIII", value: 2}, II: { name: "dII", value: 3}, I: {name: "dI", value: 4}};
let result = Object.values(blah).filter(x => x.value > 2)
console.log(result)
I would use Object.entries and reduce.
const blah = {
IV: {
name: "dIV",
value: 1
},
III: {
name: "dIII",
value: 2
},
II: {
name: "dII",
value: 3
},
I: {
name: "dI",
value: 4
}
};
var result = Object.entries(blah).reduce((obj, [key, props]) => {
if (props.value >= 3) {
obj[key] = props
}
return obj
}, {})
console.log(result)
try Object.keys(blah):
const blah = {
IV: {
name: "dIV",
value: 1
},
III: {
name: "dIII",
value: 2
},
II: {
name: "dII",
value: 3
},
I: {
name: "dI",
value: 4
}
};
var result = Object.keys(blah)
.filter(key => blah[key].value > 2)
.reduce((acc, key) => ({...acc, [key]: blah[key]}), {});
console.log(result)
What you have provided in the example is not in fact JSON (Javascript Object Notion), but an actually Javascript object, the birthplace of the JSON serialisation format.
JavaScript objects are more like dictionaries, and provide fast key/value read/writes for structured data. You cannot sort a Javascript object because it is unordered, depending on the javascript engine's implementation (V8 for Chrome, Node.js, ...).
What you can do, is get a list of keys/values/key+values as an array, and iterate over the array, either using the array's values to construct a new object, or just as a reference for a list of keys that exist in the object.
See Object.keys, Object.values and Object.entries on Mozilla MDN. Arrays are ordered, can be sorted and iterated over.

Iterate over- and easilly modify datastructure

I have to render an array of inputs out of data which would be fairly straightforward:
const [myInputs, setMyInputs] = useState([{id: 1, value: 'foo'},{id: 2, value: 'bar'}, ...])
myInputs.map(({id, value}) => <input key={id} value={value} />
the problem is that If I want to add an onChange function I have to find my object, remove it from the array, make a new object with the new values and insert it at the same position, same for every other modification I want to make to my data.
Is there a better way to accomplish the same effect (have an iterable where I can modify each value individually)?
Do it like this:
const [myInputs, setMyInputs] = useState({
nameOfInput1: {
id: 1,
value: 'foo'
},
nameOfInput2: {
id: 2,
value: 'bar'
},
})
Object.entries(myInputs).forEach(([key, field]) => (
<input
key={field.id}
value={field.value}
onChange={(newValue) => setMyInputs({ ...myInputs, key: { ...field, value: newValue } })}
/>
)
Convert the array to key value pairs. For Example:
{id: 1, value: 'foo'},{id: 2, value: 'bar'}
will be
const obj = {1: 'foo', 2: 'bar'}
So using the id you can delete, update or add the object.
delete obj[1]; //delete
obj[2] = 'new bar'; //update
obj[3] = 'new val'; //add
Also for rendering you can do Object.keys(obj) and map it to element.

Fast way to flatten an array of objects in Javascript

I have an array of generated objects like the following:
[
{obj1: {
key: 'value'
}},
{obj2: {
key: 'value2'
}},
{obj3: {
key: 'value3'
}}
]
I would like to flatten the array, with the following output:
[
{
key: 'value'
},
{
key: 'value2'
},
{
key: 'value3'
}
]
I am doing this with a for loop, which works, but the array will be quite large in size and wonder if there is a more efficient way to do this?
for (var key in array) {
let obj = array[key];
for (var key in obj) {
newArray.push(obj[key]);
}
}
output:
newArray: [
{
key: 'value'
},
{
key: 'value2'
},
{
key: 'value3'
}
]
I'm looking for the simplest method, ES6 or Lodash also welcome for solutions.
Updated to reflect correct array format.
You can simply use reduce and Object.values
let arr = [{obj1: {key: `value`}},{obj2: {key: `value2`
}},{obj3: {key: `value3`}}]
let op = arr.reduce((op,e)=> op.concat(Object.values(e)),[])
console.log(op)
You can use simple for loop when you care about speed.
let arr = [{obj1: {key: `value`}},{obj2: {key: `value2`
}},{obj3: {key: `value3`}}]
let op = []
for(let i=0; i<arr.length; i++){
let values = Object.values(arr[i])
op = op.concat(values)
}
console.log(op)
You can use Array.map, and Object.values.
Map "maps" each element in an array to a new array.
It takes each element of an array, and performs an operation on it.
The result of this operation becomes the corresponding element in a new Array.
This new Array is what's returned.
To convert Objects into Arrays: you can use Object.values, Object.keys, and Object.entries.
Object.values de-references each key in an object, and turns it into an array element holding that key's value.
const arr = [
{obj1: {key: 'value'}},
{obj2: {key: 'value2'}},
{obj3: {key: 'value3'}}
];
let newArr = arr.map(obj => (
{key: Object.values(obj)[0].key}
));
console.log(newArr);
To return an object, it must be wrapped in parenthesis.
In the first iteration, obj == { obj1: { key: 'value' }}, the first element in the input Array, arr.
And,
Object.values(obj) == [{key: 'value'}]
So, we need to grab the element at index 0 to pull the object out of the array {key: 'value'}.
Alternatively, if you know you can rely on the naming structure of the elements in your array (the outer object's key), you could do this, which may be easier to reason about:
const arr = [
{obj1: {key: 'value'}},
{obj2: {key: 'value2'}},
{obj3: {key: 'value3'}}
];
let newArr2 = arr.map( (obj, i) => (
{ key: obj['obj'+(i+1)].key }
));
console.log(newArr2);
Note: you'll need to wrap the i+1 in parenthesis, to force addition to take precedence over JS auto type conversion and string concatenation. Otherwise instead of obj1, obj2, obj3, you'll get obj01, obj11, obj21 as the object keys.

How to change nested object into array

I have a object like this.
var Obj = {
obj1 : {
val : 1,
id : 1
}
obj2 : {
val : 2,
id :2
}
obj3 : {
val : 3,
id :3
}
}
I want my obj1and all sub object into one array so I can retrieve the value. I want array in array because I want to retrieve them, Since it is dynamic I can not use Obj.obj1 therefore I want to push into array.
Can Anybody tell How Can I get that. Thanks for help
Use Object.keys and Array#map methods to convert it to an array but the order is not guaranteed since object properties don't have any order.
var Obj = {
obj1: {
val: 1,
id: 1
},
obj2: {
val: 2,
id: 2
},
obj3: {
val: 3,
id: 3
}
};
var res = Object.keys(Obj).map(function(k) {
return Obj[k];
})
console.log(res);

Javascript 'property inheritance'

Is there a way to specify common elements for object literals in an array?
For example:
var array = [ {key: "hi", label: "Hi", formatter:deleteCheckboxFormatter},
{key: "hello", label: "Hello", formatter:deleteCheckboxFormatter},
{key: "wut", label: "What?", formatter:deleteCheckboxFormatter}];
All three records use the same formatter. How would you refactor this?
A pair of alternatives come to my mind:
A helper function with the default value for the common field:
function make(key, label) {
return {'key': key, 'label': label, formatter:deleteCheckboxFormatter};
}
var array = [ make("hi", "Hi"),
make("hello", "Hello"),
make("wut", "What?")];
Or a more generic function that accepts an argument for the formatter property:
function make (formatter) {
return function (key, label) {
return {'key': key, 'label': label, 'formatter':formatter};
}
}
// a function to build objects that will have a 'fooFormatter'
var foo = make('fooFormatter');
var array = [ foo ("hi", "Hi"),
foo ("hello", "Hello"),
foo ("wut", "What?")];
And the last thing that comes to my mind is simply iterate over the array assigning the common field:
var array = [ {key: "hi", label: "Hi"},
{key: "hello", label: "Hello"},
{key: "wut", label: "What?"}];
var i = array.length;
while (i--) {
array[i].formatter = 'deleteCheckboxFormatter';
}
I used here a while loop in reverse order, because the order of iteration is not important and this type of loop performs better.
var array = [ {key: "hi", label: "Hi"},
{key: "hello", label: "Hello"},
{key: "wut", label: "What?"}];
for(var item in array)
item["formatter"] = deleteCheckboxFormatter;
You could make an object out of it using a constructor:
function Obj(key, label){
this.key = key;
this.label = label;
this.formatter = "deleteCheckboxFormatter";
}
var array = [ new Obj("hi", "Hi"),
new Obj("hello", "Hello"),
new Obj("wut", "What?") ];

Categories

Resources