Lodash forEach function omit - javascript

I have an object in my .js file (node)
var z = [
{'a': 'uno', 'b': 'dos'},
{'a': 'uno', 'b': 'dos'},
{'a': 'uno', 'b': 'dos'},
{'a': 'uno', 'b': 'dos'}
];
I would like to omit each 'a' from z object.
I'm trying with something like this, but is not working.
var y = _.forEach(z, function(n){
//console.log(_.omit(n, 'a'));
return _.omit(n, 'a');
});
console.log(y);
I tried without return, and few ways more, but didn't get it.
My jsfiddle link: http://jsfiddle.net/baumannzone/jzs6n78m/
Any help? Cheers!

Create a new array of objects, by omitting a from each of them
console.log(_.map(z, function (obj) {
return _.omit(obj, 'a');
}));
// [ { b: 'dos' }, { b: 'dos' }, { b: 'dos' }, { b: 'dos' } ]
As it is, you are omitting and creating a new object but that object is ignored by _.each. Now, we use _.map, which will gather all the values returned from the function and form a new array.
If you prefer a one-liner, create a partial function and leave only the object to be used as _, like this
console.log(_.map(z, _.partial(_.omit, _, 'a')));
// [ { b: 'dos' }, { b: 'dos' }, { b: 'dos' }, { b: 'dos' } ]

var y = _.map(z, function(n) {
return _.omit(n, 'a');
});
This will create a new array from the old one, mapping the objects in z to new objects that omit the 'a' attribute.
An alternative is to use chaining, so:
var y = _(z).map(function(n){return n.omit('a');}).value();
B

Related

javascript merge array of objects, resulting object values in array

Would like to merge an array of objects resulting in an object of unique keys and array of values (duplication of values is ok). Solutions in vanilla JS or lodash preferred.
eg - from this:
[{
a: 1,
b: 2
}, {
a: 1,
c: 3
}]
to this:
{
a: [1, 1],
b: [2],
c: [3]
}
You can use _.mergeWith() with the spread syntax to combine the objects:
const data = [{"a":1,"b":2},{"a":1,"c":3}];
const result = _.mergeWith({}, ...data, (v1 = [], v2) => [...v1, v2]);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
ES6 variant:
const a = [{
a: 1,
b: 2
}, {
a: 1,
c: 3
}]
const b = a.reduce((acc, cur) => Object.assign(acc,
...Object.keys(cur).map(key => ({ [key]: (acc[key] || []).concat(cur[key]) })))
, {})
console.log(b)
without loadash:
var t = [{
a: 1,
b: 2
}, {
a: 1,
c: 3
}];
var result = {};
debugger;
for(var i=0; i<t.length; i++){
for(var j in t[i]){
if(result.hasOwnProperty(j)){
result[j].push(t[i][j]);
}else{
result[j] = [t[i][j]];
}
}
}
console.log(result);
A quick search here in stack reveals that #elclanrs already wrote code for that here However based on the comments, it needs a little tweaking to accept an array of objects, so I added a bit of change to the original code itself.
so basically it boils to the function call:
var merge = function() {
return [].reduce.call(arguments, function(acc, x) {
for(i=0;i<x.length;i++){
Object.keys(x[i]).forEach(function(k) {
acc[k] = (acc[k]||[]).concat([x[i][k]])
});
}
return acc
},{})
}
}
Here's a snippet using the function call (with a bit of small change I put) in that post:
var x = [{a: 1, b: 2}, {a: 1,c: 3}]
var merge = function() {
return [].reduce.call(arguments, function(acc, x) {
for(i=0;i<x.length;i++){
Object.keys(x[i]).forEach(function(k) {
acc[k] = (acc[k]||[]).concat([x[i][k]])
});
}
return acc
},{})
}
y = merge(x);
alert(JSON.stringify(y));
You can use lodash#mergeWith wrapped in a lodash#spread to make lodash#mergeWith treat an array as a list of arguments. We use lodash#concat as a supporting function to concatenate an empty object (to avoid mutating the objects in the collection), the collection, and the customizer function that merges the entire collection. The customizer is composed using lodash#flow, wherein its first argument is lodash#concat that only accepts an arity of 2 using lodash#ary and the second argument uses lodash#compact -- It removes all undefined values in an array.
var result = _.spread(_.mergeWith)(
_.concat({}, data, _.flow(_.ary(_.concat, 2), _.compact))
);
var data = [{
"a": 1,
"b": 2
}, {
"a": 1,
"c": 3
}];
var result = _.spread(_.mergeWith)(
_.concat({}, data, _.flow(_.ary(_.concat, 2), _.compact))
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Replace a key in an object

I have:
var obj = {'a': {some object}, 'b': {some other object}, 'c':{some other object},...}
I want to write a function that will overwrite any single key in my original object.
myFunction(obj, {'a': {new object}});
console.log(obj);
//{'a': {new object}, 'b': {some other object}, 'c':{some other object},...}
I am using lodash. I obviously know that I can do _.keys then get the only item in the array and then assign it manually but I wonder if there is a less cumbersome way.
The _.extend function, available as Object.assign in ES6-compatible Javascript, does what you want.
_.extend({ a: 1, b: 2 }, { a: 10 })
// { a: 10, b: 2 }
The function is more flexible than simple assignment: you can add or replace any number of keys, shallow-merging the objects passed as parameters.
No need of Lodash/Underscore, this can be done in JavaScript easily.
obj[key] = newObject;
var obj = {
one: {
1: 'ONE'
},
two: {
2: 'TWO'
},
three: {
3: 'THREE'
}
};
obj['two'] = {
22: 'Two Two'
};
console.log(obj);
UPDATE:
You can use Object.assign()
Object.assign(obj, {
two: {
22: 'Two Two'
}
});

Is there a lodash function to merge two objects and delete properties of one of them if they don't exist in the other?

Consider the following two objects:
const source = {
foo: 'value',
bar: 'value',
baz: 'value'
};
const pattern = {
foo: '',
bar: ''
};
_.fn(source, pattern); // { foo: 'value', bar: 'value' }
In this example 'baz' property is deleted because it doesn't exist in the pattern.
_.pick can help
_.pick(source,Object.keys(pattern))
If you want to mutate the original source object for inline key deletion instead of returning a new one, you can do:
_.difference(_.keys(source), _.keys(pattern)).forEach(k => delete source[k])
Or just plain JS:
Object.keys(source)
.filter(k => Object.keys(pattern).includes(k))
.forEach(k => delete source[k])
I generally design for immutability, but this approach might be useful if you want to avoid the overhead of allocating a new object, or you have a lot of primitives that would need copying over by value to a fresh object.
What you can do as well, is look for intersection ofthose two objects:
var a = { 'a': 1, 'b': 2, 'c': 3 };
var b = { 'c': 3, 'd': 4, 'e': 5 };
_.intersection(_.keys(a), _.keys(b)); // ['c']

jQuery map selected object

I am working with JavaScript, could you help me please
Here is my problem.
I have this object:
var MyObj= [{ a: 0, b: "Zero", c: "x", d: "!" }, { a: 1, b: "One", c: "y", d: "#" }]
I want to change the element of selected object ("a" --> "id") to become like this:
var NewObj= [{ id: 0, b: "Zero", c: "x", d: "!" }, { id: 1, b: "One", c: "y", d: "#" }]
I tried to use $.map() method like this
NewObj= $.map(MyObj, function (obj) {
return { id: obj.a, b: obj.b, c: obj.c, d:obj.d };
});
Is there any better way to do this since I only change one element of object?
No need for ES6 / Object.assign, no need for jQuery:
Working Fiddle: https://jsbin.com/gosaqid/edit?js,console
function makeObj(obj){
return obj.map(function(el, i) {
el.id = i;
delete el.a;
return el;
});
}
Not unless you have a clone/copy/extend function available. One is coming up in new JavaScript, and jQuery has one, and it's not very hard writing your own. But it still isn't a walk in the park - you can't just rename a property, you need to copy and delete:
NewObj = MyObj.map(function(obj) {
var newobj = Object.assign({}, obj, {id: obj.a});
delete newobj.a;
return newobj;
});
In your example MyObj is an array of objects.
var object = {}
var array = []
var arrayOfObjects = [{}, {}, {}]
In your desired result, you have changed one of the keys of every object in the array.
Using map is a perfectly adequate way of doing this, in fact JavaScript's array has a built in map method.
var newArrayOfObjects = arrayOfObjects.map(function (obj) {
return {
id: obj.a,
b: obj.b,
c: obj.c
}
})
If you have a ton of keys this can get a little verbose so you can use $.extend, but chances are you're writing code for modern browsers so the whole thing can be written as such:
var newArrayOfObjects = arrayOfObjects.map(obj =>
Object.assign({}, obj, { id: obj.a })
)
update: as #Amadan suggests, you can also delete the old key if you need

Send javascript Object through $.ajax

I want to send a javascript object like this one through a $.ajax request :
var o = {
a: 1,
b: 'dummy string',
c: ['a', 1, {}],
d: {dd: 1},
e: new Date(),
f: function() {
console.log('here');
}
}
I know that i normally should use JSON.stringify before sending it to my php script. The problem is JSON.stringify, removes the properties it can't stringify :
JSON.stringify(o);
returns this ->
"{
"a":1,
"b":"dummy string",
"c":["a",1,{}],
"d":{"dd":1},
"e":"2015-11-13T21:34:36.667Z"
}"
But what shoud i do, if i want to store in a mysql column the "o" javascript object as plain text like this :
o = {
a: 1,
b: 'dummy string',
c: ['a', 1, {}],
d: {dd: 1},
e: new Date(),
f: function() {
console.log('here');
}
}
You could try this:
var o = {
a: 1,
b: 'dummy string',
c: ['a', 1, {}],
d: {dd: 1},
e: new Date(),
f: function() {
console.log('here');
}
};
o.f = o.f.toString();
var stringy = JSON.stringify(o);
document.getElementById('test2').innerHTML = stringy;
Fiddle: http://jsfiddle.net/e2cxandt/
Obviously this needs to be changed a bit so you aren't overwriting the function by maybe cloning the object but as a quick example you can see it now has the property in the string.
As someone mentioned in the comments above, war10ck, here is an example of using the replacer argument of JSON.stringify
var o = {
a: 1,
b: 'dummy string',
c: ['a', 1, {}],
d: {dd: 1},
e: new Date(),
f: function() {
console.log('here');
}
};
function replacer (key, value) {
if (typeof value === "function") {
return value.toString();
}
return value;
}
var stringy2 = JSON.stringify(o, replacer);
document.getElementById('test2').innerHTML = stringy2;
Fiddle: http://jsfiddle.net/e2cxandt/1/
a couple universal (non-specific-instance) options:
you can define a custon toJSON on any object:
Function.prototype.toJSON=function(){return String(this);};
JSON.stringify({a:1, b:function(){alert(123)}});
which shows:
{"a":1,"b":"function (){alert(123)}"}
the one caveat is that your function literal is quoted as a string and no longer a function. to fix that if needed, you can use a reviver parameter to JSON.parse().
a better option:
using a replace arg to JSON.stringify():
JSON.stringify({a:1, b:function(){alert(123)}}, function(k,v){
if(typeof v==="function") return String(v);
return v;
});
which shows:
{"a":1,"b":"function (){alert(123)}"}
that way is particularly nice because you need not modify an built-in or instance objects.

Categories

Resources