Given this JavaScript array:
var list = [1,1,1,2,2,2,2]
I want to know how I can produce an HTML list below that has each unique item in the array and number of times that they appear in the array. I just want to know the JavaScript to produce the data, I can generate the HTML.
1 is x3
2 is x4
I'm confused about how to achieve this. Basically, similar to shopping cart quantity functionality, but using the array.
http://jsfiddle.net/37ab3k00/
Use .reduce to reduce your array to an object of quantities.
var list = [1, 1, 1, 2, 2, 2, 2];
var quantities = list.reduce(function(obj, n) {
if (obj[n]) obj[n]++;
else obj[n] = 1;
return obj;
}, {});
var ul = document.querySelector("ul");
for (var n in quantities) {
ul.appendChild(document.createElement("li")).textContent = n + " has a quantity x" + quantities[n];
}
<ul></ul>
The first argument to .reduce() is a function that gets invoked for each member in the Array.
The second argument is an object that we're going to pass along to each iteration. It gets passed as the first argument to the function we provided, and we always return it so that it always gets passed as that argument. This is called the accumulator.
The n argument to the function we provided is the value of the current member in the list. So what we do is first see if our obj has a truthy n member. If so, it must have been encountered already, so we increment it. If not, we assign it the initial value of 1 to represent the first n that was found for that value.
var list = [1,1,1,2,2,2,2]
var counts = {};
for (var i = 0; i < list.length; i++) {
counts[list[i]] = 1 + (counts[list[i]] || 0);
}
Demo: http://jsfiddle.net/famn4zcL/2/
Add to HTML
var li = '';
for (var el in counts) {
li += '<li>' + el + ' is x' + counts[el] + '</li>';
}
document.getElementById('list').innerHTML = li;
Demo: http://jsfiddle.net/famn4zcL/3/
Another way would be using array of objects (those can be easily upgraded with additional data that you probably would need building products), like so:
HTML:
<span id="display"></span>
JS (plain, no Framework):
var objects = [
{prod:0,quant:00},
{prod:1,quant:11},
{prod:2,quant:22},
{prod:3,quant:33},
{prod:4,quant:44},
{prod:5,quant:55}
];
var list_of_objects = "", display_id = document.getElementById("display");
for (var key in objects) {
if (objects.hasOwnProperty(key)) {
console.log(key);
list_of_objects += '<li>'+objects[key].prod + ' has a qtty x ' + objects[key].quant+'</li>';
}
}
console.log(list_of_objects);
display_id.innerHTML = list_of_objects;
So you could easily upgrade product data with new info, like:
var objects = [
{prod:0,quant:00,url:"http://url00"},
{prod:1,quant:11,url:"http://url11"},
{prod:2,quant:22,url:"http://url22"},
{prod:3,quant:33,url:"http://url33"},
{prod:4,quant:44,url:"http://url44"},
{prod:5,quant:55,url:"http://url55"}
];
JSfiddle to play with: http://jsfiddle.net/7hokfmdu/
Related
I have some very clunky code that includes 2 for loops with if statements. They're pretty simple but I'm not getting the expected result when attempting to set the result toFixed(2). i'm trying to refactor it using arrow functions but I'm not finding anything specific to comparing 2 arrays and holding the value of one array when the same index of a 2nd array = "other fee". In total, I have 4 arrays. the first for loop looks for the feeAmts from that array and will hold the value when the feeCategory = Other Fee then it adds them. The 2nd for loop does the same thing for override fees and categories.
I guess there's really 2 questions here.
Can this be done using arrow functions?
If not, how can I get the existing code to return the expected value with toFixed(2). This code is currently only returning undefined.
function main(feeAmts, feeCategory, ovrFeeAmts, ovrFeeCategory) {
let result = 0.00;
let tmpTotalOne = 0;
let tmpTotalTwo = 0;
const otherFee = "OTHER FEE";
let ndx;
for (ndx = 0; ndx < feeAmts.length; ndx += 1) {
if (feeCategory[ndx].toUpperCase() === otherFee) {
tmpTotalOne += feeAmts[ndx];
}
}
for (ndx = 0; ndx < ovrFeeAmts.length; ndx += 1) {
if (ovrFeeCategory[ndx].toUpperCase() === otherFee) {
tmpTotalTwo += ovrFeeAmts[ndx];
}
}
let ttl = (tmpTotalOne + tmpTotalTwo);
result = (ttl.toFixed(2));
}
var result = main("_feeAmts", "_feeCategory", "_ovrFeeAmts", "_ovrFeeCategor");
const _feeAmts = [_feeAmtOne, _feeAmtTwo, _feeAmtThree, _feeAmtFour, _feeAmtFive,
_feeAmtSix, _feeAmtSeven, _feeAmtEight, _feeAmtNine, _feeAmtTen, _feeAmtEleven,
_feeAmtTwelve, _feeAmtThirteen, _feeAmtFrteen
];
const _feeCategory = ["_feeCategoryOne", "_feeCategoryTwo", "_feeCategoryThree",
"_feeCategoryFour", "_feeCategoryFive", "_feeCategorySix", "_feeCategorySeven",
"_feeCategoryEight", "_feeCategoryNine", "_feeCategoryTen", "_feeCategoryEleven",
"_feeCategoryTwelve", "_feeCategoryThirteen", "_feeCategoryFrteen"
];
const _ovrFeeAmts = [_ovrFeeAmtOne, _ovrFeeAmtTwo, _ovrFeeAmtThree, _ovrFeeAmtFour,
_ovrFeeAmtFive
];
const _ovrFeeCategory = ["_ovrFeeCategoryOne", "_ovrFeeCategoryTwo",
"_ovrFeeCategoryThree", "_ovrFeeCategoryFour", "_ovrFeeCategoryFive"
];
Recently Attended the interview, Some one asked the question like below:
var array = [0,1,2,3,4,5];
Output :
temp:
temp1:1
temp22:22
temp333:333
temp4444:4444
temp55555:55555
I tried below code it is working fine but is there any best solution for this example :
array.forEach(function(item,index){
var text ="";
if(index >= 2){
for(var j =1; j <= index; j++){
text += index;
}
console.log("temp"+text + ":" + text);
}else{
console.log("temp"+index + ":" + index);
}
});
Thanks in advance!
Using ES6 template strings and String.prototype.repeat
var array = [0,1,2,3,4,5];
array.forEach(item => {
const text = String(item).repeat(item);
console.log(`temp${text}: ${text}`);
})
And the same code translated into ES5 - this will work in all browsers starting from IE9 and above.
var array = [0,1,2,3,4,5];
array.forEach(function(item) {
var text = Array(item+1).join(item);
console.log("temp" + text + ": " + text);
})
Since String.prototype.repeat does not exist in ES5, there is a bit of a hack to generate a string of specific length with repeating characters:
Array(initialCapacity) will create a new array with empty slots equal to what number you pass in, Array.prototype.join can then be used to concatenate all members of the array into a string. The parameter .join takes is the separator you want, so, for example you can do something like this
var joinedArray = ["a","b","c"].join(" | ");
console.log(joinedArray);
However, in this case, each of the members of the array is blank, since the array only has blank slots. So, upon joining, you will get a blank string, unless you specify a separator. You can leverage that to get a repeat functionality, as you are essentially doing something like this
//these produce the same result
var repeatedA = ["","",""].join("a");
var repeatedB = Array(3).join("b");
console.log("'a' repeated:", repeatedA);
console.log("'b' repeated:", repeatedB);
Using the Array function, you can scale it to any number of repeats you want. The only trick is that you need to add 1 when creating the array, since you get one less character when joining.
You could iterate the array and iterate the count. Then display the new string.
var array = [0, 1, 2, 3, 4, 5];
array.forEach(function (a, i) {
var s = '';
while (i--) {
s += a;
}
console.log ('temp' + s + ':' + s);
});
I am writing javascript to try to do only a few simple tasks.
var series = ["A","0","0","B","0","C","0","0","D","0"];
var off = 1;
var built = 1;
var position = 1;
var masterSeries = [];
var slot = 1;
console.log(series);
function createMaster() {
for (var i = 0; i <= series.length - 1; ++i) {
masterSeries[i] = ["Mode" + off];
//console.log("Creating Internal Array #" + off);
off++
}
off = 1;
//since we already have first series we just assign it here
masterSeries[0] = series;
return masterSeries;
}
function buildAltSeriesNoNull() {
for (var i = 1; i <= series.length - 1; i++) {
slot++;
console.log("Checking Slot: " + slot);
if (series[i] != "0") {
console.log("Found Non Null, building: " + built);
//code to mutate the original array into new arrays goes here
var temp = series;
var back = temp.slice(i, series.length);
var front = temp.slice(0,i);
var newline = back.concat(front);
masterSeries[position] = newline;
position++;
console.log("Added to Master Series Mini Array:" + position);
built++;
} else {
console.log("Skipping Slot: " + slot);
}
off++;
//masterSeries[i] = ["Love" + numOffset]; //set the mode
}
console.log(masterSeries);
}
console.log(createMaster()); //Create the MasterSeries Display the Banks
console.log("Memory banks have been created, and we have a valid series of numbers to work with!");
console.log('\n');
console.log(buildAltSeriesNoNull());
I have an hard coded array of 10 index's that hold possible letters
there will be a random amount of letters populating the 10 slots, it should not matter if the first index is null or not null
For Example
A00B0C00D0
ABC00D00EF
0A0B0C0D0E
The zero's should be treated as null (will come in handy in a second)
First I want the program to iterate through each index after the first and
A. determine if it is a null or a valid letter
B. If it is null, then skip to next index
C. If it has a valid letter than it will create a new array and 'resort' the original array into a custom sorted array that looks like this. (using one of the example original arrays above)
ORIGINAL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->A00B0C00D0
Program checks index 2, and it is null, move to next, checks index 3 it is null, move to next. Index 4 has a value, "B" So now program creates a new array simply called array2nditerate and the array now looks like this
SECOND ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->B0C00D0A00
THIRD ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->C00D0A00B0
FOURTH ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->D0A00B0C00
So it is creating a new array for each unique letter based on the position in the original array it sat.
So once It creates all the unique sorted arrays for each slot that had a value. I would then need it to do the entire same process but this time to the positions in the original array that had null values only...so for example it would look like this.
ORIGINAL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->A00B0C00D0
FIRST NULL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->00B0C00D0A
SECOND NULL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->0B0C00D0A0
THIRD NULL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->0C00D0A00B
FOURTH NULL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->00D0A00B0C
FIFTH NULL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->0D0A00B0C0
SIXTH NULL ARRAY
index-->[0,1,2,3,4,5,6,7,8,9]
Value-->0A00B0C00D
If you notice it created 4 Non Null Arrays custom sorted because there were only 4 letters in the array of 10 possible index positions. it created six non nulls because 10 positions -4 non null arrays is 6 null arrays
I am not sure as to which method is quicker, better. Iterating with one for loop and sorting out into a pile of null arrays and sorting into a pile of non null arrays, or writing two separate functions that iterate
once through looking only for non null index's and sorting that way
sorting through looking for null index's and sorting that way
This is based on the thought of maintaining the original array and works only with two abstraction, the offset of the found letters and zeros.
I think, a simple iteration should sort out zero and letter indices.
this.array.forEach(function (a, i) {
a === '0' ? that.indexZero.push(i) : that.indexLetter.push(i);
});
Working example:
function ClassWithoutName(data) {
var that = this;
this.array = data.split(''),
this.indexLetter = [],
this.indexZero = [];
this.array.forEach(function (a, i) {
a === '0' ? that.indexZero.push(i) : that.indexLetter.push(i);
});
}
ClassWithoutName.prototype = {
constructor: ClassWithoutName,
getItem: function (index) {
return this.array[index % this.array.length];
},
getArray: function (offset) {
offset = offset || 0;
return this.array.map(function (_, i, o) {
return o[(i + offset) % o.length];
});
}
};
var instanceWithoutName = new ClassWithoutName('A00B0C00D0');
console.log('data: ' + instanceWithoutName.getArray().join(''));
console.log('letters:');
instanceWithoutName.indexLetter.forEach(function (a, i) {
console.log(i + ': offset: ' + a + ' ' + instanceWithoutName.getArray(a).join(''));
});
console.log('zeros:');
instanceWithoutName.indexZero.forEach(function (a, i) {
console.log(i + ': offset: ' + a + ' ' + instanceWithoutName.getArray(a).join(''));
});
console.log('special selected item, here 2nd abstraction of letter element 3:');
console.log(instanceWithoutName.getItem(instanceWithoutName.indexLetter[2] + 3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Link to jsFiddle
I have many elements containing text in which I am using parseInt() to grab the values from a specific number of elements (based on the current month) and a specific selector wildcard and push those values into one of six arrays for use elsewhere. I am trying to clean up the code and make a compact loop to complete all of this.
I am able to get everything to work if I use six separate for loops, but I thought I might try to see if it is able to be done in one single loop.
So in the for loop below, I am trying to make the jQuery wildcard selector for the element ID be the current value of i (from statusArray) by trying something like $('[id*=statusArray[i]]) but that doesn't seem to be working.
Then I would like to push the data into the predefined appropriate array by something like statusArray[i]Array.push(...) but that doesn't work either. I've tried concatenating various ways but can't seem to get it to work.
Any help would be appreciated! Thank you in advance!
HTML:
<div id="jan_connected"></div> <!-- left empty to test for NaN -->
<div id="jan_busy">100</div>
<div id="jan_noanswer">100</div>
<div id="jan_abandoned">100</div>
<div id="feb_minutes">100</div>
<div id="feb_totals_calls_c">100</div>
<div id="feb_connected">100</div>
<div id="feb_busy">100</div>
<div id="feb_noanswer">100</div>
<div id="feb_abandoned">100</div>
Javascript:
var connectedArray = [];
var busyArray = [];
var noanswerArray = [];
var abandonedArray = [];
var minutesArray = [];
var callsArray = [];
// var date = new Date();
// var dateNumber = 1 + date.getMonth();
var dateNumber = 2;
var statusArray = ['minutes', 'total_calls', 'connected', 'busy', 'noanswer', 'abandoned']
for (i=0; i<dateNumber; i++) {
// Below I would like the id* to equal the current value of the statusArray iteration
if (isNaN(parseInt($('[id*=statusArray[i]]').slice(i).html()))) {
statusArray[i]Array.push("0"); // Trying to push into the appropriate array dynamically
} else {
statusArray[i]Array.push(parseInt($('[id*=statusArray[i]]').slice(i).html()));
}
}
You have syntax errors in couple of places..
this line
$('[id*=statusArray[i]]')
supposed to be
$('[id*=' + statusArray[i] + ']')
And
statusArray[i] Array.push("0");
should be
statusArray[i].push("0");
Push method is available on a Array , but statusArray[i] is not an array but a string.
Looks like you are looking for something like this
var connectedArray = [];
busyArray = [];
noanswerArray = [];
abandonedArray = [];
minutesArray = [];
callsArray = [];
dateNumber = 2;
statusArray = ['minutes', 'total_calls', 'connected', 'busy', 'noanswer', 'abandoned'];
var obj = {
'minutes': minutesArray,
'totals_calls': callsArray,
'connected': connectedArray,
'busy': busyArray,
'noanswer': noanswerArray,
'abandoned': abandonedArray
};
for (i = 0; i < statusArray.length; i++) {
$('[id*="' + statusArray[i] + '"]').each(function () {
var val = $(this).html();
if (isNaN(parseInt(val))) {
obj[statusArray[i]].push("0");
} else {
obj[statusArray[i]].push(val);
}
});
}
console.log('Minutes Array: ' + obj['minutes']);
console.log('Total Calls Array: ' + obj['totals_calls']);
console.log('Connected Array: ' + obj['connected']);
console.log('No Answer Array: ' + obj['noanswer']);
console.log('Abandoned Array: ' + obj['abandoned']);
console.log('Busy Array: ' + obj['busy']);
Check Fiddle
I'm creating a small game and I have a peace of code that collects the pressed keys during an interval of time.
var pressedKeys = [];
setTimeout(function() {
for(var i = 0; i < pressedKeys.length; i++)
alert("Time is up you have inputed " + pressedKeys[i] + " length " + pressedKeys.length);
}, 3000);
$(document).keydown(function(evt) {
var key = evt.keyCode;
if (pressedKeys.length < 1) {
pressedKeys[0] = key;
} else {
pressedKeys[pressedKeys.length + 1] = key;
}
});
I'm new to javascript and I can't understand why I have unidentified values in the array. The funny thing to me is if I do the loop with a foreach I do not get the unidentified values.
Can some one please explain this to me. I would be very thankful.
This...
pressedKeys[pressedKeys.length + 1] = key;
should be this...
pressedKeys[pressedKeys.length] = key;
Since Array indices are zero-based, the current last item in the Array will be its length - 1, which means the next item to fill will be the one at its .length.
You can actually get rid of the if statement...
$(document).keydown(function(evt) {
pressedKeys[pressedKeys.length] = evt.keyCode;
});
It starts off with a .length of 0, so the first entry will be at index 0, which makes the .length equal to 1, so the next entry will be at index 1, and so on...
Because of this:
} else {
pressedKeys[pressedKeys.length + 1] = key;
}
The length property returns the length of an array. Arrays are zero-based, so when you refer to the lengthth index, you're referring to an non-existent element.
When you add an element at position length + 1, you're creating a gap between the last existing and new element.
This happens:
var pressedKeys = [];
var length = pressedKeys.length; // Equal to zero, 0
pressedKeys[length + 1] = key; // Inserts key at position 0 + 1 = 1
// result: pressedKeys = [undefined, key]
To solve the issue, don't add +1, or use the push method:
pressedKeys.push(key);
pressedKeys[pressedKeys.length + 1] = key;
This will actually skip elements. Arrays are zero-indexed.
Let's say you have 3 elements in the array, they will be:
pressedKeys[0]
pressedKeys[1]
pressedKeys[2]
When that line is ran pressedKeys.length will be 3, thus inserting the value into pressedKeys[4]. This will make pressedKeys[3] undefined.
The line should be pressedKeys[pressedKeys.length] = key, or better yet, don't use the length, just push onto the array.
$(document).keydown(function(evt) {
var key = evt.keyCode;
pressedKeys.push(key); // this will add to the end of the array,
// no need to calculate the position
});