Related
Having a hard time understanding for loops in arrays. Trying to create a Thank You card creator and these are the steps I'm trying to follow:
Create a new, empty array to hold the messages
Iterate through the input array and inside the loop build out the 'thank you' message for each name using string interpolation, then add that message to the new array you created
After the loop finishes and all of the messages have been added to the new array, return the new array.
const names = []
function writeCards(names, event) {
for (let i = 0; i < names.length; i++) {
console.log(`Thank you, ${names[i]} for the wonderful ${event} gift!`);
return names;
}
Not sure if I'm on the right track. Thanks for your help!
I know your question is focused on for loop, but just in case, you might be interested in using map to achieve the desired result in a more concise manner:
const names = ["Joe", "Nina"]
function writeCards(names, event) {
return names.map(name=> `Thank you, ${name} for the wonderful ${event} gift!`)
}
console.log(writeCards(names, "birthday"))
You can use Array.push()
function writeCards(names, event) {
let messages = []
for (let i = 0; i < names.length - 1; i++) {
messages.push("Thank you, " + names[i] + " for the wonderful " + event + " gift!")
}
return messages;
}
well the i had this issue
i had an empty array outside a loop and wanted to update it inside a loop
and finally return an array with alot of indexes
//ie
//let arr = []
//LOOP then runs
//then console.log(arr) //console shows [1,2,3,4,5,6,7]
this is how you do it
let arr = []
let realArray = [1,2,3,4,5]
for (let index = 0; index < realArray.length; index++) {
const element = realArray[index]
arr.push(element)
}
console.log(arr)//your arr = 1,2,3,4,5
this is my first answer here
function writeCards(names, event) {
// 1) Create a new, empty array to hold the messages.
// So, this should be done within the function. We want to be
// able to update this locally-scoped array with the information
// we get from each name in the array, combined with the event
const messages = [];
for (let i = 0; i < names.length; i++) {
// 2) using string interpolation
// What's great is that you've already discovered template strings
// String concatenation has its uses but this far better.
const message = `Thank you, ${names[i]}, for the wonderful ${event} gift!`;
// So, instead of logging the message to the console
// we're going to push it to the messages array
messages.push(message);
}
// 3) After the loop finishes and all of the messages
// have been added to the new array, return the new array.
return messages;
}
console.log(writeCards(['Bob', 'Sue'], 'wedding'));
I would rather suggest to go with #DoneDeal0 answer's.
In case, if you would like to go with for loop, there's one more cleaner way to go with it. You can use forEach() function given by javascript, as it takes two parameters in it, first is the value of each index and second is the index number itself.
Note: forEach() is just similar to for(i=0; i<n; i++).
names = ["Robert", "King", "Joey"];
function writeCards(names) {
let messages = [];
names.forEach((name, index) => {
messages.push("Thank you, " + name + " at " + index + " for the wonderful gift");
});
return messages;
}
console.log(writeCards(names));
I have this String:
['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']
I want to get the keys 'TEST1-560' which is always fist and "car" value.
Do you know how I can implement this?
This is a very, very scuffed code, but it should work for your purpose if you have a string and you want to go through it. This can definitely be shortened and optimized, but assuming you have the same structure it will be fine.:
// Your data
var z = `['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']`;
var testName = z.substring(2).split("'")[0];
var dividedVar = z.split(",");
for (var ind in dividedVar) {
if (dividedVar[ind].split(":")[0] === '"car"') {
var car = dividedVar[ind].split(":")[1].split("}")[0].substring(1,dividedVar[ind].split(":")[1].split("}")[0].length-1);
console.log(car)
}
}
console.log(testName);
output:
BLUE
TEST1-560
In a real application, you don't need to log the results, you can simply use the variables testName,car. You can also put this in a function if you want to handle many data, e.g.:
function parseData(z) {
var testName = z.substring(2).split("'")[0];
var dividedVar = z.split(",");
for (var ind in dividedVar) {
if (dividedVar[ind].split(":")[0] === '"car"') {
var car = dividedVar[ind].split(":")[1].split("}")[0].substring(1, dividedVar[ind].split(":")[1].split("}")[0].length - 1);
}
}
return [testName, car]
}
This will return the variables values in an array you can use
const arr = ['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']
const testValue = arr[0];
const carValue = JSON.parse(arr[1]).data[0].car;
console.log(testValue);
console.log('-----------');
console.log(carValue);
If your structure is always the same, your data can be extracted like above.
I have the following data structure which is a list of lists.
Input Data:
const attributes = {
AO:(15174) [Number …]
jointId:(15174) [Number …]
paletteIdx:(15174) [Number …]
position:(15174) [Array(3) …]
normal:(15174) [Array(3) …]
....//additional variable amount of properties
}
expected output:
[AO[0], jointId[0], PaletteIdx[0], position[0][0],
position[0][1], position[0][2], normal[0][0],
normal[0][1], normal[0][2], AO[1], jointId[1], ...]
I need to interleave the lists into one combined flat array. I have tried a few different solutions (nested loops) that didn't seem to scale. My latest attempt is using eval for some code generation to coerce a nested loop solution into one pass.
const attributeNames = Object.keys(attributes);
const funcBody = attributeNames.map((attributeName) => {
return `attributes.${attributeName}[index],`;
}).join('\n');
const output = eval(`
attributes[attributeNames[0]].reduce((acc, value, index) => {
acc = acc.concat(${funcBody});
return acc;
}, []);
`);
This is a non frequent operation that I can maybe move to an offline process, unfortunately, that would be a large refactor of an existing system.
(By the way, to avoid browser interruptions, one can also utilize a web worker.)
Just going with your example, which did not include in the output an element I inserted to make one array longer than the other three, what I saw in the output was tantamount to a column by column traversal of the lists that also assumes they are of equal length.
We can easily code that with a for loop. Please include more specific details about what your needs are if this would not meet them. For elements that are arrays, we can use a destructuring assignment.
const attributes = {
AO:[1,2,3],
jointId:[4,5,6],
paletteIdx:[[7,8,9], [10,11,12], [13,14,15]],
position:[[16,17,18], [19,20,21], [22,23,24]]
}
const attributeNames = Object.keys(attributes);
const funcBody = attributeNames.map((attributeName) => {
return `attributes.${attributeName}[index],`;
}).join('\n');
const output = eval(`
attributes[attributeNames[0]].reduce((acc, value, index) => {
acc = acc.concat(${funcBody});
return acc;
}, []);
`);
console.log('\'output\' from code in the question: ' + JSON.stringify(output));
var output1 = [];
var n = attributes[ Object.keys(attributes)[0] ].length;
for (let col=0; col<n; col++){
for (let row in attributes){
if (Array.isArray(attributes[row][col]))
output1.push(...attributes[row][col])
else
output1.push(attributes[row][col]);
}
}
console.log('\'output1\' from column traversal: ' + JSON.stringify(output1));
I don't see where you needed nested loops. It appears to be quite straightforward:
const { AO: {length}, AO, jointId, paletteIdx, position, normal } = attributes;
const output = []; // test whether using `new Array(length * 9);` is better
for (let i=0, j=0; i<length; i++) {
output[j++] = AO[i];
output[j++] = jointId[i];
output[j++] = PaletteIdx[i];
output[j++] = position[i][0];
output[j++] = position[i][1];
output[j++] = position[i][2];
output[j++] = normal[i][0];
output[j++] = normal[i][1];
output[j++] = normal[i][2];
}
I can't imagine anything being faster. Since you are not using previously-unknown properties in the code, I don't think dynamic code generation would be of any help here.
I'm trying to break up a string like this one:
fname=bill&mname=&lname=jones&addr1=This%20House&...
I want to end up with an array indexed like this
myarray[0][0] = fname
myarray[0][1] = bill
myarray[1][0] = mname
myarray[1][1] =
myarray[2][0] = lname
myarray[2][1] = jones
myarray[3][0] = addr
myarray[3][1] = This House
The url is quite a bit longer than the example. This is what I've tried:
var
fArray = [],
nv = [],
myarray = [];
fArray = fields.split('&');
// split it into fArray[i]['name']="value"
for (i=0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push(nv[0],nv[1]);
nv.length = 0;
}
The final product is intended to be in 'myarray' and it is, except that I'm getting a one dimensional array instead of a 2 dimensional one.
The next process is intended to search for (for example) 'lname' and returning the index of it, so that if it returned '3' I can then access the actual last name with myarray[3][1].
Does this make sense or am I over complicating things?
Your line myarray.push(nv[0],nv[1]); pushes two elements to the array myarray, not a single cell with two elements as you expect (ref: array.push). What you want is myarray.push( [nv[0],nv[1]] ) (note the brackets), or myarray.push(nv.slice(0, 2)) (ref: array.slice).
To simplify your code, may I suggest using Array.map:
var q = "foo=bar&baz=quux&lorem=ipsum";
// PS. If you're parsing from a-tag nodes, they have a property
// node.search which contains the query string, but note that
// it has a leading ? so you want node.search.substr(1)
var vars = q.split("&").map(function (kv) {
return kv.split("=", 2);
});
For searching, I would suggest using array.filter:
var srchkey = "foo";
var matches = vars.filter(function (v) { return v[0] === srchkey; });
NB. array.filter will always return an array. If you always want just a single value, you could use array.some or a bespoke searching algorithm.
for (var i = 0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push([nv[0],nv[1]]);
}
nv.length = 0; is not required, since you're setting nv in each iteration of the for loop.
Also, use var i in the for-loop, otherwise, you're using / assigning a global variable i, that's asking for interference.
I need some help with extracting values from a cookie using javascript.
The string in a cookie looks something like this:
string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2'
By using string.split() and string.replace() and a some ugly looking code I've somehow managed to get the values i need (price, name, shipping, quantity). But the problem is that sometimes not all of the strings in the cookie are the same. Sometimes the sting in a cookie will look something like this :
string = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'
with some items having color and size as parameters and sometimes only one of those.
Is there some more efficient way to explain to my computer that i want the part of the string after 'price=' to be a variable named 'price' etc.
I hope I'm making sense I've tried to be as precise as I could.
Anyway, thank you for any help
EDIT: I just wanted to say thanks to all the great people of StackOverflow for such wonderfull ideas. Because of all of your great suggestions I'm going out to get drunk tonight. Thank you all :)
Let's write a parser!
function parse(input)
{
function parseSingle(input)
{
var parts = input.split('||'),
part,
record = {};
for (var i=0; i<parts.length; i++)
{
part = parts[i].split('=');
record[part[0]] = part[1];
}
return record;
}
var parts = input.split('++'),
records = [];
for (var i=0; i<parts.length; i++)
{
records.push(parseSingle(parts[i]));
}
return records;
}
Usage:
var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2';
var parsed = parse(string);
/* parsed is:
[{id: "1", price: "500", name: "Item name", shipping: "0", quantity: "2"},
{id: "2", price: "1500", name: "Some other name", shipping: "10", quantity: "2"}]
*/
You can achieve this using regular expressions. For example, the regex /price=([0-9]+)/ will match price=XXX where XXX is one or more numbers. As this part of the regex is surrounded by parenthesis it explicitly captures the numeric part for you.
var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2'
var priceRegex = /price=([0-9]+)/
var match = string.match(priceRegex);
console.log(match[1]); // writes 500 to the console log
Try that:
var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2';
var obj = new Array();
var arr = string.split('||');
for(var x=0; x<arr.length;x++){
var temp = arr[x].split('=');
obj[temp[0]] = temp[1]
}
alert(obj['id']); // alert 1
First, split your string into two (or more) parts by ++ separator:
var strings = myString.split('++');
then for each of the strings you want an object, right? So you need to have an array and fill it like that:
var objects = [];
for (var i = 0; i < strings.length; ++i) {
var properties = strings[i].split('||');
var obj = {};
for (var j = 0; j < properties.length; ++j) {
var prop = properties[j].split('=');
obj[prop[0]] = prop[1]; //here you add property to your object, no matter what its name is
}
objects.push(obj);
}
thus you have an array of all objects constructed from your string. Naturally, in real life I'd add some checks that strings indeed satisfy the format etc. But the idea is clear, I hope.
If you can replace the || with &, you could try to parse it as if it were a query string.
A personal note - JSON-formatted data would've been easier to work with.
I would attach the data to a javascript object.
var settingsObj = {};
var components = thatString.split('||');
for(var j = 0; j < components.length; j++)
{
var keyValue = components[j].split('=');
settingsObj[keyValue[0]] = keyValue[1];
}
// Now the key value pairs have been set, you can simply request them
var id = settingsObj.id; // 1 or c1
var name = settingsObj.name; // Item Name, etc
You're already using .split() to break down the string by || just take that a step further and split each of those sections by = and assign everything on the left the field and the right the value
This should get the first match in the string:
string.match(/price=(\d{1,})/)[1]
Note this will only match the first price= in the string, not the second one.
If you can use jQuery, it wraps working with cookies and lets you access them like:
Reading a cookie:
var comments = $.cookie('comments');
Writing a cookie:
$.cookie('comments', 'expanded');
This post by someone else has a decent example:
http://www.vagrantradio.com/2009/10/getting-and-setting-cookies-with-jquery.html
If you can't use jQuery, you need to do standard string parsing like you currently are (perhaps regular expressions instead of the string splitting / replacing might trim down your code) or find some other javascript library that you can use.
If you like eye candies in your code you can use a regexp based "search and don't replace" trick by John Resig (cached here) :
var extract = function(string) {
var o = {};
string.replace(/(.*?)=(.*?)(?:\|\||$)/g, function(all, key, value) {
o[key] = value;
});
return o;
};
Then
var objects = string.split('++'),
i = objects.length;
for (;i--;) {
objects[i] = extract(objects[i]);
}
You could do something like this, where you eval the strings when you split them.
<html>
<head>
<script type="text/javascript">
var string = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'
var mySplitResult = string.split("||");
for(i = 0; i < mySplitResult.length; i++){
document.write("<br /> Element " + i + " = " + mySplitResult[i]);
var assignment = mySplitResult[i].split("=");
eval(assignment[0] + "=" + "\""+assignment[1]+"\"");
}
document.write("Price : " + price);
</script>
</head>
<body>
</body>
</html>
var str = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'
var items = str.split("++");
for (var i=0; i<items.length; i++) {
var data = items[i].split("||");
for (var j=0; j<data.length; j++) {
var stuff = data[j].split("=");
var n = stuff[0];
var v = stuff[1];
eval("var "+n+"='"+v+"'");
}
alert(id);
}
EDIT: As per JamieC's suggestion, you can eliminate eval("var "+n+"='"+v+"'"); and replace it with the (somewhat) safer window[n] = v; -- but you still have the simple problem that this will overwrite existing variables, not to mention you can't tell if the variable color was set on this iteration or if this one skipped it and the last one set it. Creating an empty object before the loop and populating it inside the loop (like every other answer suggests) is a better approach in almost every way.
JSON.parse('[{' + string.replace(/\+\+/g, '},{').replace(/(\w*)=([\w\s]*)/g, '"$1":"$2"').replace(/\|\|/g, ',') + '}]')
Convert the string for JSON format, then parse it.