Convert string literals in an array to variable name - javascript

I'm new to javascript. I am trying to store object variable names in an array but the way I'm doing it, the array values become strings. Is there a way to change these values from strings to the object variable names? In the following code, the last statement is what I would like to use but it generates "undefined" because, I think, it's seen as a string. Thanks!
var plan1 = {
name: "Lisa",
price: 5.00,
space: 100
}
var plan2 = {
name: "John",
price: 2.00,
space: 150
}
var myArray = [];
for (var i = 0; i < 2; i++) {
myArray[i] = "plan" + (i + 1);
}
alert(plan2.name);
alert(myArray[1].name);

Disclaimer: it's a very bad style, try to avoid it. Look at http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html
You can consider using eval:
for (var i = 0; i < 2; i++) {
myArray[i] = eval("plan" + (i + 1));
}

You can't build the name like you are trying to do and get it to store the object with the same name. What you have in myArray is the strings "plan1" and "plan2".
You would have to do something like myArray[0] = plan1; myArray[1] = plan2; Then it should work in the array like you want it to.

Don't try to do that programmatically. Just build your array literal out of the parts that you want it to contain:
var plan1 = {
name: "Lisa",
price: 5.00,
space: 100
};
var plan2 = {
name: "John",
price: 2.00,
space: 150
};
var myArray = [plan1, plan2];
Or even don't use those variables for the objects at all, and directly put them in the array structure:
var myArray = [{
name: "Lisa",
price: 5.00,
space: 100
}, {
name: "John",
price: 2.00,
space: 150
}];

you can use
myArray[i] = window["plan" + (i + 1)];
working copy at http://plnkr.co/edit/7pY4Lcmx6wN1rQk9rklu?p=preview

Related

Javascript, Working with array of objects. Take string, seperate by comma, and assign values to object

I'm pretty new to Javascript and would appreciate any help.
So taking a string that looks like this: "John Doe, 5554443333, Jane Doe, 5555555555"
We are to assign each person to an object, then assign this object to an array, and print the array to display our players. The expected output would be:
[{ player: 'John Doe', contact: 5554443333}, { player: 'Jane Doe', contact: 5555555555}]
my current Output is:
[{ player: 'Jane Doe', contact: 5555555555}, , { player: 'Jane Doe', contact: 5555555555}]
So the current problem is that it puts two comma's between the player objects, and also that it is listing the second player twice.
My code is as follows:
function playerManager(players)
{
var blank = []; // blank array to return per requirements (nil, none, null, or empty string)
var info = players.split(','); // Split our input string, into a string array, split at comma
var data = []; // Create array to hold our players, then return.
// function to create player
var player =
{
player: "name",
contact: "contact"
};
// check if our string is empty, nil, none, or null, if it is , return our blank array
if(players == "" || players == "nil" || players == "None" || players == "null")
{
return blank;
}
for( i = 0; i < info.length - 1; i+=2)
{
player.player = info[i];
player.contact = info[i+1];
data[i] = player;
}
return data;
}
I appreciate any and all help.
So there's a couple of things going wrong here.
Easy one first: because of the way you're iterating, i+=2, you're pushing the second object into the third, or i[2], location.
An easy way to fix is to iterate by one (i++) up to info.length / 2, but use i * 2 in your function
Ex:
for( i = 0; i < info.length / 2; i++)
{
player.player = info[i * 2];
player.contact = info[i * 2 + 1];
data[i] = player;
}
Now the tougher bit. When you assign an object to a variable, and either assign it to another variable or push it into an array, you're not creating a whole new object - you're simply referring to the exact same object, but with another name.
Here's a little snippet to demonstrate:
var a = {name: 'Joe'};
var b = a;
a.name = 'George';
console.log(b.name); // This will output 'George'
The simplest fix for you, I think, is to simply push an "anonymous" object [that's probably a misnomer] into the array.
Further refactoring our loop from earlier:
for( i = 0; i < info.length / 2; i++)
{
data[i] = {
player: info[i * 2],
contact: info[i * 2 + 1]
}
}
And finally, one more small edit - the best way to "push" an item into an array at the end is to use Array.prototype.push, which will automatically fix the "extra comma" issue.
So finally, here's what your code should look like:
for( i = 0; i < info.length / 2; i++)
{
data.push({
player: info[i * 2],
contact: info[i * 2 + 1]
});
}
Look, the problem is, when you creating a player with info and then insert it into an player array in first round, your playerArr[0] is referencing to the player you created(which is an object). So far there is no problem. But when it goes round two, you updated the player object, which also make the playerArr[0] changed too! It is because playerArr[0] is actually a pointer which pointing to the player object( and you just updated it)!
This should work:
function playerManager(players)
{
var info = players.split(','); // Split our input string, into a string array, split at comma
var data = []; // Create array to hold our players, then return.
for( i = 0; i < info.length/2; i++)
{
data[i] = {player:info[i*2],contact:info[i*2+1]};
}
return data;
}
console.log(playerManager("John Doe, 5554443333, Jane Doe, 5555555555"))
As you are incremented your for..loop with i+=2 and you are pushing value like this
data[i] = player;
So initially for 0 index is right but after next increment i will be 2. And next value will assign on 2 index so your 1 index will be empty.
So instead of assigning value in array index you could use Array.prototype.push() method inside of for loop.
DEMO
const str = "John Doe, 5554443333, Jane Doe, 5555555555";
function playerManager(players) {
let arr = players.split(','),
data = [];
for (let i = 0; i < arr.length; i += 2) {
data.push({
player: arr[i],
contact: arr[i + 1],
})
}
return data;
}
console.log(playerManager(str))
.as-console-wrapper {max-height: 100% !important;top: 0;}
A simpler and shorter alternative in a declarative style, assuming the player name and contact are always in the same order:
const input = 'John Doe, 5554443333, Jane Doe, 5555555555';
const result = input.split(',').map(str => str.trim()).reduce((all, item, i, arr) => {
if (i % 2 === 1) {
all.push({player: arr[i-1], contact: Number(item)});
}
return all;
}, []);
console.log(result);

NodeJS loop through string and get the exact output

In NodeJS I have a string like this
"Package=Package&Qty=1&Price=123?Package=Package Two&Qty=3&Price=702?Package=Package Three&Qty=1&Price=199?Package=Package One&Qty=4&Price=852?"
In the string you can see there are multiple Package, Qty and Price. Now I want to send email for each Qty and Package. So if you see Package Two it has Qty 3. So in that case there it will send 3 emails with Package and Price. So basically it will send email for each Qty with corresponding Package and Price.
So for now I have my code like this
var string = "Package=Package&Qty=1&Price=123?Package=Package Two&Qty=3&Price=702?Package=Package Three&Qty=1&Price=199?Package=Package One&Qty=4&Price=852?";
var packArr = string.split('?');
var PackageName;
var PackagePrice;
for (var i = 0; i < packArr.length; i++) {
if( packArr[i].length > 0 ) {
let packageQty = packArr[i].split('&');
for (var j = 0; j < packageQty.length; j++) {
if( packageQty[j].match(/Package=/i) ) {
PackageName = packageQty[j].replace(/Package=/g,'');
console.log(PackageName);
}
if( packageQty[j].match(/Price=/i) ) {
PackagePrice = packageQty[j].replace(/Price=/g,'');
console.log(PackagePrice);
}
if (packageQty[j].match(/Qty=/i)) {
var ret = packageQty[j].replace(/Qty=/g,'');
var Pck = Number(ret);
for (var k = 1; k <= Pck; k++) {
console.log(k);
console.log('Package Name ' + PackageName);
console.log('Package Price ' + PackagePrice);
//send email with Package Name, Package Price
if( k == Pck ) {
break;
}
}
}
}
}
}
The above code actually not working properly. It is not getting the Package and Price properly for each loop. So can someone tell me how to do this in a easy way? Any help and suggestions will be really appreciable.
Here's a much cleaner way using querystring package
const string = "Package=Package&Qty=1&Price=123?Package=Package Two&Qty=3&Price=702?Package=Package Three&Qty=1&Price=199?Package=Package One&Qty=4&Price=852?";
const qs = require('querystring');
// We split the string into multiple valid query strings.
// We strip the empty item due to the '?' at the end using .filter(Boolean)
const items = string.split('?').filter(Boolean);
// We loop through each group
for(const query of items) {
// Parse the query string of each group
const { Package, Qty, Price } = qs.parse(query);
for(let i = 0; i < Number(Qty); i++) {
// We send the email here <Qty> times.
console.log('Package Name ' + Package);
console.log('Package Price ' + Price);
}
}
I don't know how you feel about libraries, but Ramda (disclaimer: I'm one of the authors) is well-suited to data-transformations. And this screams for some straightforward data transformation.
I might use it to write a conversion function that changes your initial data into something like:
[
{Package: "Package", Price: 123, Qty: 1},
{Package: "Package Two", Price: 702, Qty: 3},
{Package: "Package Three", Price: 199, Qty: 1},
{Package: "Package One", Price: 852, Qty: 4}
]
This new format should then be easy to work with.
Here is a implementation that does this:
const {pipe, split, filter, map, fromPairs, evolve} = R;
const str = "Package=Package&Qty=1&Price=123?Package=Package Two&Qty=3&Price=702?Package=Package Three&Qty=1&Price=199?Package=Package One&Qty=4&Price=852?";
const convertToObjects = pipe(
split('?'),
filter(Boolean),
map(split('&')),
map(map(split('='))),
map(fromPairs),
map(evolve({Price: Number, Qty: Number}))
);
console.log(convertToObjects(str))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
map, split, and filter should be obvious.
fromPairs turns [['a', 1], ['b', 2]] into {a: 1, b: 2}.
evolve takes a specification mapping property names to transformation functions, and transforms an object by applying those functions to the relevant properties, keeping all other properties intact. Here we use it with the JS Number function to convert {Package: 'Foo', Qty: '2', Price: '456'} into {Package: 'Foo', Qty: 2, Price: 456}.
and pipe creates a pipeline of functions in which the output of one function becomes the input to the next. Values supplied to the resulting function are sent to the first one and the result of the last one is returned.
Extending #Marcos-casagrande example here without external dependency using plain javascript
const string = "Package=Package&Qty=1&Price=123?Package=Package Two&Qty=3&Price=702?Package=Package Three&Qty=1&Price=199?Package=Package One&Qty=4&Price=852?";
// We split the string into multiple valid query strings.
// We strip the empty item due to the '?' at the end using .filter(Boolean)
const items = string.split('?').filter(Boolean);
// We loop through each group
items.map(query => {
// Parse the query string of each group
const {
Package,
Qty,
Price
} = query.split('&').reduce((acc, cur) => {
let arr = cur.split('=');
return {
...acc,
[arr[0]]: arr[1]
};
}, {});
for (let i = 0; i < Number(Qty); i++) {
// We send the email here <Qty> times.
console.log('Package Name ' + Package);
console.log('Package Price ' + Price);
}
})
Another way using only regexes and a few array methods, not requiring nested loops
var input = "Package=Package&Qty=1&Price=123?Package=Package Two&Qty=3&Price=702?Package=Package Three&Qty=1&Price=199?Package=Package One&Qty=4&Price=852?"
var results = input
.split('?')
.map(s => /^Package=(.*?)&Qty=(.*?)&Price=(.*?)$/.exec(s))
.filter(s => s)
.map(s => ({
package: s[1],
qty: parseFloat(s[2]),
price: parseFloat(s[3])
}))
console.log(JSON.stringify(results, null, 4))
Here is a pure JS alternative, please take a look.
function extract(name, string) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(string);
return results == null ? null : results[1];
}
function parse(string) {
items = string.split('?');
results = [];
for (var i in items) {
if (items[i].length == 0) continue;
var item = '?' + items[i];
results.push({
package: extract("Package", item),
qty: extract("Qty", item),
price: extract("Price", item)
})
}
return results;
}
str = "Package=Package&Qty=1&Price=123?Package=Package Two&Qty=3&Price=702?Package=Package Three&Qty=1&Price=199?Package=Package One&Qty=4&Price=852?";
document.getElementById('output').innerText = JSON.stringify(parse(str));
<div id='output'></div>

JavaScript - create a string by combining other strings at different positions

Suppose I have 3 strings: s1 = "ab", s2 = "cd", s3 = "ef".
The goal is to create another string by combining s1, s2, and s3. The catch is that the user can decide the positions of those 3 strings. So, for instance:
s1 - position 3;
s2 - position 2;
s3 - position 1
Result:
efcdab.
My question is, what is the best way to solve this problem? My solution was to create 3 objects that will each hold the string position and value as properties, add the objects into and array and then sort the array using the position property of each object, but I just have the feeling that there is a better solution.
Thanks in advance!
Just giving it a try where you strPos is the user defined object for ordering the strings
var s1 = 'ab';
var s2 = 'cd';
var s3 = 'ef';
var strs = {s1:s1,s2:s2,s3:s3};
var strPos = {1:'s1',2:'s3',3:'s2'};
var fin = '';
for(var i=1;i<=3;i++){
fin += strs[strPos[i]];
}
console.log(fin);
#Five from your comments the answer can be changed to follow your object structure as below
var definedOrderedList = [{
value: 'ab',
position: 2
}, {
value: 'cd',
position: 1
}, {
value: 'ef',
position: 3
}];
var strArr = [];
for (var o in definedOrderedList) {
strArr[definedOrderedList[o].position] = definedOrderedList[o].value;
}
var finalString = strArr.join('');
console.log(finalString);
If your strings and positions are given as an array of {value, position} objects, you can use Array.reduce to order and concatenate them to an ordered string in linear time:
let strings = [
{value: "ab", position: 3},
{value: "cd", position: 2},
{value: "ef", position: 1}
];
let string = strings.reduce((sorted, next) => {
sorted[next.position - 1] = next.value;
return sorted;
}, []).join("");
console.log(string); // "efcdab"
You can use two objects. One that has string and values, lets say values like
{
s1: 'String1',
s2: 'String2',
s3: 'String3'
}
and one lets say position object like
{
p1: 'store user entry for position1',
p2: 'store user entry for position2',
p3: 'store user entry for position3'
}
and access first object like this values[position['p1']] add to values[position['p2']] and so on
Based on how you described your object structure, looks like you will have an array like this(chosen one possible random ordering):
var arr = [ { value: "ab", position: 2 }, { value: "cd", position: 1 }, { value: "ef", position: 3 } ];
Then you can sort the array based on the position and then concatenate the strings.
var arr = [ { value: "ab", position: 2 }, { value: "cd", position: 1 }, { value: "ef", position: 3 } ];
arr.sort((a,b) => a.position - b.position);
var ans="";
for(var i=0;i<arr.length;i++) {
ans += arr[i].value;
}
console.log(ans);
I'm not sure how you are having them pick the order, but with this all you have to do is fill in the options for them to choose and it does the rest of the work. This can be made prettier by a lot, but that is up to you and how you take user interaction.
var selections = ["ab", "cd", "ef"];
var str = "";
while(selections.length){
var choice = prompt("Type part of the string from below that you want to add first:\n " + " " + selections);
var index = selections.indexOf(choice);
if(index !== -1){
str += choice;
selections.splice(index, 1);
}
}
alert("You typed: " + str);

Convert an array of object to array of string?

I'm having an array of object like this-
var person = [
{name: 'saprsh', age: 22, address:'XYZ'},
{name: 'Ankur', age: 23},
{name: 'Richa', age:25, adddress:'ABX', email:'abc#xyz.co'}
];
now i want output like this
var string_person = [{sparsh22XYZ},{ankur23},{Richa25ABXabc#xyz.co}];
is their any way to get output like this in javascript, jquery, Angular.js.
Any other web used language is approved.
Check out this jsfiddle. You'll see both Array.prototype.reduce and Array.prototype.map used, both with the same results.
This is classic reduce:
var people = person.reduce(function(agg, p) {
return agg.concat([p.name + p.age + p.address]);
}, []);
The above uses Array.prototype.reduce.
In other words, when you want all the properties of an object or array "reduced" into something, then the most semantic go-to option is probably Array.prototype.reduce in this case.
However, Array.prototype.map can also do the job quite cleanly:
var people = person.map(function(p) {
return p.name + p.age + p.address;
});
This is an argument, now, between readability/complexity vs. semantics.
To limit incidental complexity (in the form of readability), I might go for the map function, even though you could argue this is technically a paradigmatic reduction.
Try this, this method suitable for different object names, it will work good.
var person = [
{name: 'saprsh', age: 22, address:'XYZ'},
{name: 'Ankur', age: 23},
{name: 'Richa', age:25, adddress:'ABX', email:'abc#xyz.co'}
];
var result = person.map(function(p){ return Object.keys(p).map(function(k){return p[k]}).join("");})
You can do it like this.
var person = [
{name: 'saprsh', age: 22, address:'XYZ'},
{name: 'Ankur', age: 23, address:'ABC'}
];
var test = person.map(function(one){
var properties = Object.getOwnPropertyNames(one);
return properties.map(function(prop){
return one[prop];
}).join('');
});
console.log(test);
I think it will help you.
var person = [
{name: 'saprsh', age: 22, address:'XYZ'},
{name: 'Ankur', age: 23, address:'ABC'}
];
var stringarray=[];
// $.each(person, function (i, d) {
// stringarray.push(d.name + d.age + d.address);
// });
//for(var i = 0; i < person.length; i++){
// stringarray.push(person[i].name + person[i].age + person[i].address);
//}
var stringarray = person.map(function(p) {
return p.name + p.age + p.address;
});
console.log(stringarray);
Result: ["saprsh22XYZ", "Ankur23ABC"]
Plz Try this one.
I assume you want a array of strings.
[{sparsh22XYZ},{ankur23ABC}]
is not such an array.
If you want
[ "sparsh22XYZ", "ankur23ABC" ]
you can simply go with
Plain old Javascript:
var string_person = [];
for (var i = 0; i < person.length; i++) {
string_person.push(person[i].name+person[i].age+person[i].address);
}
Underscore.js library
If all you need is a list of values of one of the object properties, it's easiest to go with underscore.js library.
var string_person = _.pluck(person, 'name');
http://underscorejs.org/#pluck
Call the below function on any array of Objects with any number of parameters, it will return you what you want.
function getStringArray(array){
var resultArray = [];
for (i = 0; i < array.length; i++) {
var result = "";
var keysArray = Object.keys(array[i]).sort()
for(j = 0; j < keysArray.length; j++){
result = result+array[i][keysArray[j]];
}
resultArray.push(result);
}
return resultArray;
}
var string_person = [];
for(var i = 0; i < person.length; i++){
string_person.push(person[i].name + person[i].age + person[i].address);
}
Updated:
Also You can use Underscore:
var string_person = _.map(person, function(p){return p.name + p.age + p.address;});
I guess you want to join all members of the object to a string. There are two ways to do this:
// iterate through the array of persons
for (var index = 0; index < person.length; index++) {
var obj = person[index]; // save the object temporally
person[index] = ''; // place an empty string at the index of the object
// iterate through all members of the object using the "in"-operator
for (var member in obj) {
person[index] += obj[member]; // add the value of the member to the string
}
}
The problem with this technique is, I cannot guarantee that it will join the values of the members in the order you want. It should join them in the order in which the members were defined.
Anyway this solution works fine but only in your case:
// iterate through the array of persons
for (var index = 0; index < person.length; index++) {
// place a string which contains the joined values of the members in the right order at the index of the object
person[index] = [
person[index].name,
person[index].age,
person[index].address
].join('');
}

How do you convert an array of JavaScript objects to a single object?

I have this array:
var objectArray = [{url:"www.google.com", id: "google"},
{url:"www.apple.com", id: "apple"},
{url:"www.facebook.com", id: "facebook"}];
Is it possible to convert to a JavaScript object that is formed like this:
var newObject = {"google": "www.google.com",
"apple": "www.apple.com",
"facebook": "www.facebook.com"};
You can manually loop over the array and convert it.
var obj = {};
for (var i = 0; i < objectArray.length; i++) {
obj[objectArray[i].id] = objectArray[i].url;
}
var m={};
objectArray.forEach(function (i){m[i.id]=i.url})

Categories