How can I remove object from array, with Lodash? - javascript

I'm trying to remove an object from an array using Lodash.
In server.js (using NodeJS):
var lodash = require('lodash')();
var rooms = [
{ channel: 'room-a', name: 'test' },
{ channel: 'room-b', name: 'test' }
]
I tried with two commands and it did not work:
var result = lodash.find(rooms, {channel: 'room-a', name:'test'});
var result = lodash.pull(rooms, lodash.find(rooms, {channel: 'room-a', name:'test'}));
Here's the output of console.log(result):
LodashWrapper {
__wrapped__: undefined,
__actions__: [ { func: [Function], args: [Object], thisArg: [Object] } ],
__chain__: false,
__index__: 0,
__values__: undefined }
Can someone help me? Thank you!

_.remove() is a good option.
var rooms = [
{ channel: 'room-a', name: 'test' },
{ channel: 'room-b', name: 'test' }
];
_.remove(rooms, {channel: 'room-b'});
console.log(rooms); //[{"channel": "room-a", "name": "test"}]
<script src="https://cdn.jsdelivr.net/lodash/4.14.2/lodash.min.js"></script>

I'd go for reject() in this scenario. Less code:
var result = _.reject(rooms, { channel: 'room-a', name: 'test' });

require('lodash')()
Calling the lodash function (by ()) creates a LoDash object that wraps undefined.
That's not what you want; you want the lodash function itself, which contains static methods.
Remove that.

Related

Return all values of nested arrays using string identifier

Given an object searchable, is there a simple way of returning all the id values using lodash or underscore.js (or equivalent) where I can define the path to id?
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
I am looking to see if this is possible in a manner similar to how we can use lodash.get e.g. if we wanted to return the things array from searchable we could do
const things = _.get(searchable, 'things');
I can't seem to find anything similar in the documentation. I am looking for something
that could contain an implementation similar to:
_.<some_function>(searchable, 'things[].properties[].id')
Note: I am well aware of functions like Array.map etc and there are numerous ways of extracting the id property - it is this specific use case that I am trying to figure out, what library could support passing a path as a string like above or does lodash/underscore support such a method.
Found a solution using the package jsonpath
const jp = require('jsonpath');
const result = jp.query(searchable, '$.things[*].properties[*].id')
console.log(result);
// outputs: [ 'd1-i1', 'd1-i2', 'd2-i1', 'd2-i2' ]
you can do it easily in plain js
like this
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
const search = (data, k) => {
if(typeof data !== 'object'){
return []
}
return Object.entries(data).flatMap(([key, value]) => key === k ? [value]: search(value, k))
}
console.log(search(searchable, 'id'))
_.map and _.flatten together with iteratee shorthands let you expand nested properties. Every time you need to expand into an array, just chain another map and flatten:
const searchable = {
things: [
{
id: 'thing-id-one',
properties: [
{ id: 'd1-i1' },
{ id: 'd1-i2' },
]
},
{
id: 'thing-id-two',
properties: [
{ id: 'd2-i1' },
{ id: 'd2-i2' },
]
}
]
}
// Let's say the path is "things[].properties[].id"
const result = _.chain(searchable)
.get('things').map('properties').flatten()
.map('id').value();
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/underscore#1.13.4/underscore-umd-min.js"></script>

Node.js - Access key from object

I try to access a key from an object I get back from an API but when I do so, I get the key of the object in a strange format.
This is what I get when I console.log the object (booking):
{ createdDate: 2018-03-26T11:36:09.694Z,
date: 2018-03-26T13:45:00.000Z,
...,
vouchers:
List [
{ value: 100,
code: 'vouchercode',
...
}
]
}
When I then try to console.log the "vouchers" key:
booking.vouchers
I get this:
{ [Function: f]
_receiver: {
createdDate: 2018-03-26T11:36:09.694Z,
date: 2018-03-26T13:45:00.000Z,
...,
vouchers: List [ [Object] ] },
_scope:
{ where: { bookingId: 5ab8db29b24991b50704445a },
collect: 'voucher',
include: 'voucher' },
_targetClass: 'Voucher',
find: [Function],
getAsync: [Function],
...,
}
Why do I get it in this format and how do I convert it to a normal object like this?:
vouchers: [
{ value: 100,
code: 'vouchercode',
...
}
]
I hope the problem is understandable and some of you can help :)
Edit:
This is my code:
Booking.findById id, {include:[ 'vouchers']}, (err, booking)->
console.log booking
vouchers = booking.vouchers
console.log vouchers
*Note: I know this is coffeescript but I don't think thats the problem

Keys to Mongoose Object are different from property names

In order to troubleshoot an error I have been getting, I wrote the following snippet:
var myFunction = function(obj) {
var keys = Object.getOwnPropertyNames(obj);
console.log(obj);
console.log(keys);
}
When running my function within a mongoose query callback, the console logs this:
{_id: 5a8g123vjsdj83nf8afvn48,
username: 'Player1',
adv1: { name: 'a', type: '!' },
adv2: { name: 'a', type: '!' },
adv3: { name: 'a', type: '!' },
__v: 0,
invitations: [ 'PlayTest1', 'PlayTest2' ] }
[ '$__', 'isNew', 'errors', '_doc', '$init' ]
Now as far as I understand it, the last line in the console (separated for reading convenience) should read:
[ '_id', 'username', 'adv1', 'adv2', 'adv3', '__v', 'invitations ]
My question is why does the keys obj I create in myFunction not contain the properties names shown when I log the actual object?
Mongoose document fields are stored in obj._doc
console.log displays the document fields due to an .inspect function attached to the document object.
Use node --inspect if you want to debug something.

JS – How to build a dynamic nested object of arrays with objects etc. from string

This is a nice evening project, but actually i'm stuck with some headache.
All I need is a function like this example:
result = set("itemCategories[0].items[0].name", "Test")
which should return:
{ itemCategories: [
{
items: [ {name: "Test"} ]
}
}]
...and in case of the given attribute "itemCategories[1].items[2].name" this result:
{ itemCategories: [
null,
{
items: [
null,
null,
{name: "Test"}
]
}
}]
Use lodash#set:
result = lodash.set({}, "itemCategories[0].items[0].name", "Test")
If you are asking about the vanilla JavaScript Set method then you could do this.
/* this is what you are trying to get.
{ itemCategories: [
{
items: [ {name: "Test"} ]
}
}]
*/
var mySet = new Set(); // your set object.
Create your data (number, text, string, object, array, null).
ver data1 = 365;
ver data2 = 'Dragonfly';
ver data3 = {name: 'Bobby', age: 20000, job: 'dj'};
Then you just add to that set using its add method.
mySet.add(data1);
mySet.add(data2);
mySet.add(data3);
So to get what you are looking for you would write this.
var itms = {items: [{name: 'test'}]};
mySet.add(itms);
The good thing about set is that is like an array. So you can use forEach.
mySet.forEach( function(val){
console.log(val); // gets all your data.
});
You can even check if a value is in your data using the has method.
mySet.has(365); // true
mySet.has(36500000); as false
JavaScript Set

How to iterate thru multiple values in a single key in mongoose

I have a web app which uses MongoDB as database and I'm trying to iterate thru multiple values inside a single property named passport.
This is my schema:
var EmployeeDBSchema = new Schema({
/* Passport tab schema */
passportInfo: {
passportDetails: []
},
And here's how it looks in Robomongo:
I tried checking if this can be retrieved as an array, so I did below:
console.log(_.map(results, _.property('passportInfo')));
passportArr = _.map(results, _.property('passportInfo'));
console.log("is passport array? " + _.isArray(passportArr));
Result:
Now since it was positive, I tried iterating thru it like a normal array using the ff. code:
_.forEach(passportArr, function (value, key) {
_.forEach(passportArr[key], function(value2, key2){
console.log(key2 + " >> " + value2);
});
});
However, what I got was this:
How can I get the values of passportExpiry, passportNumber and countryOfOrigin?
I'm really having a hard time over this. Hoping somebody can help.
Thank you.
EDIT: Not sure if this will help but, I got the idea for the structure from this Plunker. Main idea behind Passport was the user can add an unlimited number of passport information (hence the passportInfo array). I'm trying to retrieve the data here so I can render it as a CSV file.
UPDATE:
Here's the expanded results as requested (from console.log):
full results
[ { _id: dummyiddontmind123,
employeeID: '123asd12',
desiredRoleOther: 'Other role',
desiredRole3: 'Role 3',
desiredRole2: 'Role 2',
desiredRole1: 'The Role',
isOpenToIntlAssignment: 'Y',
employeeName: 'Jane Doe',
yrsInIT: 1,
visaInfo:
[ { visaCountryOfOrigin: [Object],
visaNumber: 'asd',
visaEntry: 'Single',
visaExpiry: '2017-03-16T16:00:00.000Z',
visaStatus: 'expired' } ],
passportInfo:
[ { countryOfOrigin: [Object],
passportNumber: [Object],
passportExpiry: '2017-03-03' },
{ countryOfOrigin: [Object],
passportNumber: [Object],
passportExpiry: '2017-03-08T16:00:00.000Z' },
{ countryOfOrigin: [Object],
passportNumber: [Object],
passportExpiry: '2017-03-10T16:00:00.000Z' } ] } ]
[ [ { passportExpiry: '2017-03-03',
passportNumber: { '0': 'EB1234567' },
countryOfOrigin: { '0': 'Philippines' } },
{ passportExpiry: '2017-03-08T16:00:00.000Z',
passportNumber: { '1': 'AS1234' },
countryOfOrigin: { '1': 'Japan' } },
{ passportExpiry: '2017-03-10T16:00:00.000Z',
passportNumber: { '2': 'AX123' },
countryOfOrigin: { '2': 'Singapore' } } ] ]
Your data inside passportInfo is a bit off, probably due to some copy-paste error after outputting it.
I take it you want to export all stored passport information into a csv of format country; number; expiry.
The first thing you want to make sure is that the actual data and the data you expect are structurally the same. If not, you can still add transformation steps before (e.g. flatten arrays or transform objects from {0: 123} to [123]).
As soon as this is under control, you can start by mapping the objects of employee.passportInfo from a structured object to an array of information necessary for your csv. This happens using Array.prototype.map.
I added another step inside that map to make sure an object of passportInfo.passportNumber of the form {0: 123} is transformed into an array [123]. This array is then used to map to a single line of your csv by adding passportInfo.countryOfOrigin and .passportExpiry.
// The following code snippets only operates on one employee. If you have an array use an iteration function depending on your needs.
const employee = { _id: 123,
employeeID: '123asd12',
desiredRoleOther: 'Other role',
desiredRole3: 'Role 3',
desiredRole2: 'Role 2',
desiredRole1: 'The Role',
isOpenToIntlAssignment: 'Y',
employeeName: 'Jane Doe',
yrsInIT: 1,
visaInfo: [ {
visaCountryOfOrigin: [Object],
visaNumber: 'asd',
visaEntry: 'Single',
visaExpiry: '2017-03-16T16:00:00.000Z',
visaStatus: 'expired' }
],
passportInfo: [ {
countryOfOrigin: 'ABC',
passportNumber: { 0: '123123123' },
passportExpiry: '2017-03-03'
}, {
countryOfOrigin: 'DEF',
passportNumber: { 0: '321321321', 1: '123123123' },
passportExpiry: '2017-03-08T16:00:00.000Z'
}, {
countryOfOrigin: 'GHI',
passportNumber: { 0: '654654654' },
passportExpiry: '2017-03-10T16:00:00.000Z'
} ]
};
const flattenPassportNumbers = numbers =>
Object.keys(numbers).map(key => numbers[key]);
const info = employee.passportInfo.map(({passportNumber, passportExpiry, countryOfOrigin}) =>
flattenPassportNumbers(passportNumber).map(number =>
[countryOfOrigin, number, passportExpiry]
)
);
const flattenLine = ([line]) => line;
const joinLine = (line) => line.join('; ');
const lines = info.map(flattenLine);
console.log(lines.map(joinLine));
console.log(lines.map(joinLine).join('\n'));
If there's something you don't understand, please don't hesitate to ask.

Categories

Resources