Reducing objects properties to get new object - javascript

What I have,
var oldUsers = [{
"SID": "S-12",
"Username": "bring.on",
"firstname": "bring",
"lastname": "on",
"email": "emasdklhsjas#gmnailasd.com"
// and so on... 10 more properties
}, {
"SID": "S-13",
"Username": "bring.on1",
"firstname": "bring",
"lastname": "on1",
"email": "sdf#gmnailasd.com"
// and so on... 10 more properties
},
// n numbers of more users...];
What I want,
var newUsers = [{ FullName : "bring on - emasdklhsjas#gmnailasd.com",
value : S-12
},
{ FullName : "bring on1 - sdf#gmnailasd.com",
value : S-13
}, // more users with same properties as abvove
];
What I tried but failed,
var newUsers = $.each(oldUser, function () {
return u = {
value : this.SID,
FullName : this.firstname + " " + this.lastname + " - " + this.email,
};
});
It needs to work on IE-8+ not sure what I am doing wrong really.
All I want is to reduce properties of object in array and get a new object.

Array.prototype.map() can be used to create new array using Plain old Vanilla JavaScript.
The map() method creates a new array with the results of calling a provided function on every element in this array
var newUsers = oldUser.map(function(obj){
return {
value : obj.SID,
FullName : obj.firstname + " " + obj.lastname + " - " + obj.email,
}
});
Note: It will work with IE9+
Using jQuery.map()
var newUsers = jQuery.map(oldUser, function(obj){
return {
value : obj.SID,
FullName : obj.firstname + " " + obj.lastname + " - " + obj.email,
}
});

Your problem is that the .each function doesn't return anything.
http://api.jquery.com/jquery.each/. It iterates over the collection of objects and performs and action on each one. This is different than the functional concept of the higher order function map, which is used to translate one collection into another. (JQuery has a map function too.)
To fix your problem you either need to do:
var newArray = []
var newUsers = $.each(oldUser, function () {
newArray.push ({
value : this.SID,
FullName : this.firstname + " " + this.lastname + " - " + this.email,
});
});
or
var newArray = $.map(oldUsers, function (u,i) {
return {
value : this.SID,
FullName : u.firstname + " " + u.lastname + " - " + u.email,
};
});
Personally, I would go with the second one, as it reduces the number of side effects in your code.
Edit: Apparently, map does not work in IE 8, so the top one is the more correct approach.

Try the following:
var newUsers = [];
$.each(oldUser, function () {
newUsers.push({
value : this.SID,
FullName : this.firstname + " " + this.lastname + " - " + this.email,
});
});
Here is a fiddle for it. Check your console log for the outcome when you run the fiddle.

try this!
var newArr= [];
$.each(users, function (index , user) {
newArr.push({
value : user.SID,
FullName : user.firstname + " " + user.lastname + " - " + user.email,
});
});

Your object is an array of objects, so make use of Array map method:var result = oldUsers.map(function(e){
return { Fullname : e.firstname + e.lastname, value : e['SID']};
});

Related

Lodash filter out rougue items from object

I am creating an object from a json file events.json using lodash map and uniqby.
Very rarely I get an event that has a country other than "United Kingdom". I don't need them in the results, how would I go about 'not mapping' the events that are not in the "United Kingdom". Thanks
var _ = require('lodash');
var data = require('./events.json')
var newEventList = _.uniqBy(data.events,'id').map(events => ({
id: events.id ,
name: events.name ,
venue: events.venue.name ,
address: events.place.location.street + " " + events.place.location.city + " " + events.place.location.zip + " " + events.place.location.country
}));
I have looked at _.filter but am not sure of where to use it within the map function.
You can use filter before or after map. But before map it will be more useful.
var newEventList = _.uniqBy(data.events,'id').filter(event => event.place.location.country === 'United Kingdom').map(event => ({
id: event.id ,
name: event.name ,
venue: event.venue.name ,
address: event.place.location.street + " " + event.place.location.city + " " + event.place.location.zip + " " + event.place.location.country
}));
But the question is why you need uniq by id? Usually id is a property that should be uniq

How to choose what argument a variable is assigned to in a function? -Javascript

Given a normal function as such;
function descriptions(awesome, cool, alright){
return (awesome || "no one") + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
descriptions("jane", "jack", "jefferson");
//returns "jane is awesome. jack is cool. jefferson is alright."
I would like to use the same function, but would only like to pass it the final two arguments like so:
descriptions(cool : "john", alright : "jane"); //I would like a statement similar to this that works.
//should return "no one is awesome. jack is cool. jefferson is alright."
How would the above be done?
Something different syntactically but similar semantically might be achieved using object destructuring
function descriptions({ awesome = 'no one', cool, alright }) {
return awesome + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
Then you just invoke it with an object with corresponding properties:
descriptions({ cool: 'a', alright: 'b'});
You can do this by passing an object:
function descriptions(info) {
// Avoid TypeError if no argument is passed
if (!info) {
info = {};
}
return (info.awesome || "no one") + " is awesome. " + (info.cool || "no one") + " is cool. " + (info.alright || "no one") + " is alright.";
}
// Use:
console.log(descriptions({
awesome: "Strong Bad",
cool: "The Cheat",
alright: "Strong Sad"
}));
Yes you can certainly achieve this!
You can use a clever trick many developers use to set a variable to a default value if one is not provided.
function descriptions(awesome, cool, alright){
awesome = awesome || "";
if (awesome === "")
{
return "no one" + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
else{
return awesome + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
}
console.log(descriptions(undefined, "jack", "jefferson"));
Here is the working code. You could also pass an empty string.
In ECMAScript 6, this can sort of be done if you change your parameters to receive an object and take advantage of destructuring assignment.
function descriptions({awesome: awesome = "no one", cool: cool = "", alright: alright = ""} = {}) {
return awesome + " is awesome. " +
cool + " is cool. " +
alright + " is alright";
}
var res = descriptions({ cool: "john", alright: "jane" });
document.body.textContent = res;
So we have someone of an emulation of named parameters. Only thing extra needed by the caller is the curly braces.
Of course browser support is limited, but transpilers are available.
You could use a different approach:
var coolLevels = {
isCool: ["Jack", "John"]
, isAlright: ["Jane", "Jefferson"]
, isAwesome: []
}
function describe(people, coolLevel, phrase) {
return people.filter(function(person){
return Boolean(coolLevel.indexOf(person))
}).join(", ") + phrase
}
function descriptions(people){
var awesome = describe(people, coolLevels.isAwesome, ' is awesome.')
var cool = describe(people, coolLevels.isCool, ' is cool.')
var alright = describe(people, coolLevels.isCool, ' is alright.')
return awesome + cool + alright
}
demo: https://jsbin.com/kahawuhelu/edit?js,console,output
That is not possible in any variety of ECMAScript (including JavaScript).
It is theoretically possible to do things like use conditional, custom logic:
function(a,b,c){
if(arguments.length === 1) {
// we're in object mode;
b = a.b
c = a.c
a = a.a || 'default';
}
}
But that is not a built in part of the language.
This is NOT possible, for example:
function foo(a,b,c){return a/(b || 1) + c;}
foo({c:1,b:2,a:3})
There is also the possibility to conditionally define values based on number of arguments:
function say (a,b,c) {
if(arguments.length === 2) {
c = b;
b = a;
a = 'cat';
}
console.log('a ' + a + ' likes a ' + b + ' and a ' + c)
}
say('dog', 'bone', 'walk') // a dog likes a bone and a walk
say('mouse', 'bowl of milk') // a cat likes a mouse and a bowl of milk
You can pass undefined, null or "" as the first parameter. E.g:
descriptions(null, "jack", "jefferson");
Since you already use awesome || "no one", any falsy value will be good enough.
Another approach would be changing the function to receive an object:
function descriptions(options) {
return (options.awesome || "no one") + " is awesome. " + options.cool + " is cool. " +
options.alright + " is alright";
}
descriptions({ cool: "jack", alright: "jefferson" });
Now, depending on your browser support, you can use ES6 destructuring parameters:
const descriptions = ({ awesome = 'no one', cool, alright }) => (
`${awesome} is awesome. ${cool} is cool. ${alright} is alright`
);
descriptions({ cool: 'jack', alright: 'jefferson' });

undefined gets outputted instead of object properties

Why the undefined gets outputted instead of the object properties.
Created a function, defined setters for the parameters and function to output the string consisting of the parameters.
Below is the snippet for the app.js file.
// app.js
function Fruit(theColor, sweetness, theName, theOrigin) {
//properties
this.theColor = theColor;
this.sweetness = sweetness;
this.theName = theName;
this.theOrigin = theOrigin;
//functions
this.showName = function () {
console.log("This is a " + this.theName);
};
this.showLand = function () {
this.theOrigin.forEach(function (arg) {
console.log("Grown in: " + arg);
});
};
}
var mango = new Fruit("Yellow", 9, "Mango", ["India", "Central America"]);
console.log(mango.showName() + " " + mango.showLand());
This line:
console.log(mango.showName() + " " + mango.showLand());
calls those functions, then outputs their return values with a space between them. Neither showNames nor showLand returns anything, and so calling them gives you the result undefined.
If you just want to call those, just call them, without using console.log to output their result. E.g., replace:
console.log(mango.showName() + " " + mango.showLand());
with
mango.showName();
mango.showLand();
If you want them to return, rather than display, their result, edit them to do so. You'll have to decide how you want showLand to separate lines (e.g., with a \n, or by returning an array, etc.).
For instance, this showName will return a string, and showLand will return an array:
//functions
this.showName = function () {
return "This is a " + this.theName;
};
this.showLand = function () {
return this.theOrigin.map(function (arg) {
return "Grown in: " + arg;
});
};
which you could then call like this:
console.log(mango.showName() + ". " + mango.showLand().join(", "));
Live Example:
function Fruit(theColor, sweetness, theName, theOrigin) {
//properties
this.theColor = theColor;
this.sweetness = sweetness;
this.theName = theName;
this.theOrigin = theOrigin;
//functions
this.showName = function () {
return "This is a " + this.theName;
};
this.showLand = function () {
return this.theOrigin.map(function (arg) {
return "Grown in: " + arg;
});
};
}
var mango = new Fruit("Yellow", 9, "Mango", ["India", "Central America"]);
console.log(mango.showName() + ". " + mango.showLand().join(", "));

Steam trade-offer-manager get items info shorten

I'm trying to build a new project.
It's going to be a tradebot for a website, now to store my received items into my database i whould like some info send with each item (being the name , asseid , tradeid,...).
The following code works.
offers.on('receivedOfferChanged', function (offer, oldState) {
logger.info(offer.partner.getSteam3RenderedID() + " Offer #" + offer.id + " changed: " + TradeOfferManager.getStateName(oldState) + " -> " + TradeOfferManager.getStateName(offer.state));
// Alert us when we accept an offer
if (offer.state == TradeOfferManager.ETradeOfferState.Accepted) {
offer.getReceivedItems(function (err, items) {
if (err) {
logger.error("Couldn't get received items: " + err);
} else {
var names = items.map(function(item) {
return item.name;
});
var assetids = items.map(function(item) {
return item.assetid;
});
// Log a comma-separated list of items received
logger.info("Received: " + names + " " + assetids.join(', '));
}
});
}
});`
But the thing is, is there any way to shorten the following code :
var names = items.map(function(item) {
return item.name;
});
var assetids = items.map(function(item) {
return item.assetid;
});
So it gets the item name , assetid, ... out of the array and stores them in sperate variables ?
You can use push() method to add values into both arrays in a single loop. Try:
var names = [],
assetids = [];
items.forEach(function(item) {
assetids.push(item.assetid);
names.push(item.name);
});

Problem with anonymous function and undefined members values

I asked a question here:
Extending javascript literal object
which was solved because I forgot return. Now I didn't forget return and I got undefined again, why ?
<script>
var secretAgent = (function(){
var person = {},
firstName = "James",
lastName = "Bond";
person.WhoAreYou = function() {
alert("My name is " + this.lastName + ", " + this.firstName + " " + this.lastName);
};
return person;
})();
</script>
<script>
secretAgent.WhoAreYou();
</script>
Update: why mine doesn't work whereas I think I did the same thing as the one below that works:
http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/
//Revealing Module Pattern (Public & Private)
var skillet = (function() {
var pub = {},
//Private property
amountOfGrease = "1 Cup";
//Public property
pub.ingredient = "Bacon Strips";
//Public method
pub.fry = function() {
console.log( "Frying " + pub.ingredient );
};
//Private method
function privateWay() {
//Do something...
}
//Return just the public parts
return pub;
}());
//Public Properties
console.log( skillet.ingredient ); //Bacon Strips
//Public Methods
skillet.fry();
//Adding a public property to a Module
skillet.quantity = 12;
console.log( skillet.quantity ); //12
//Adding a public method to a Module
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
};
try {
//Would have been successful,
//but can't access private variable
skillet.toString();
} catch( e ) {
console.log( e.message ); //amountOfGrease is not defined
}
You need to declare those properties on the literal itself (rather than separate unrelated variables), like this:
var secretAgent = (function(){
var person = { firstName: "James", lastName: "Bond" };
person.WhoAreYou = function() {
alert("My name is " + this.lastName + ", " + this.firstName + " " + this.lastName);
};
return person;
})();
You can test it out here.
There are two problems here, as I see it.
You did forget the return, again. :-) The WhoAreYou function doesn't actually return anything, it just alerts. Hence secretAgent.WhoAreYou() returns undefined too.
The alert shows "My name is undefined, undefined undefined". This is because of the scope of the variables used. You assign the WhoAreYou to person, and within the body you reference this.lastName. The this here refers to the person variable, and as you can see this object does not have a lastName property.
There are two ways then that you can fix the latter issue. Firstly, by adding the name variables to the person object:
var secretAgent = (function(){
var person = {};
person.firstName = "James";
person.lastName = "Bond";
person.WhoAreYou = function() {
alert("My name is " + this.lastName + ", " + this.firstName + " " + this.lastName);
};
return person;
}
)();
// Although the first three lines would be more natural as:
var person = { firstname: "James", lastName: "Bond" };
Secondly, you can instead choose to drop the this reference, which will instead refer to the local variables you just defined:
var secretAgent = (function(){
var person = {},
firstName = "James",
lastName = "Bond";
person.WhoAreYou = function() {
alert("My name is " + lastName + ", " + firstName + " " + lastName);
};
return person;
}
)();
You'll of course need to add appropriate returns to the WhoAreYou function in both examples.
Remove "this" from the variables since you are setting them as a var with in the anonymous function, using this points to that function and not "Person" which is where you are now calling them.
<script>
var secretAgent = (function(){
var person = {},
firstName = "James",
lastName = "Bond";
person.WhoAreYou = function() {
alert("My name is " + lastName + ", " + firstName + " " + lastName);
};
return person;
}
)();
</script>
<script>
secretAgent.WhoAreYou();
</script>
example here: JSFiddle
Why not just:
var secretAgent = {
firstName: "James",
lastName: "Bond",
whoAreYou: function() {
alert("My name is " + this.lastName + ", " +
this.firstName + " " + this.lastName);
}
};
The way you defined firstName and lastName are not fields to object person itself. But they are upper values to function WhoAreYou. So you could write the function like this:
person.WhoAreYou = function() {
alert("My name is " + this.lastName + ", " + this.firstName + " " + this.lastName);
};
Its like if those were private variables to the function. The alternative is declaring as filelds to the object itself like this:
var person = {
firstName: "James",
lastName: "Bond",
};
The the method whould work as you wrote it.
The variable this is person in your case, also firstName and lastName are defined as local variables, but not as properties of the person, so you can just access them within the anonymous function by names:
var secretAgent = (function(){
var person = {},
firstName = "James",
lastName = "Bond";
person.WhoAreYou = function() {
alert("My name is " + lastName + ", " + firstName + " " +lastName);
};
return person;
})();
secretAgent.WhoAreYou();

Categories

Resources