Beginner programmer here. I'm struggling with an assignment that's taking input text, splitting the words into single array items and then listing the total number of each words in an output. The splitting of the input works fine, but I need to check the array for duplicate items and remove that item (need to keep it unique) while also increasing the count on that particular word.
The idea was to make an array consisting of the words alone, and another that keeps track of the count. Glad to receive tips to use a simpler approach as well.
And yes, I know there is several solutions to this problem on SO, but I dont quite understand how to fix this particular code using functions.
function gen()
{
var arr = [];
var counter = [];
var str = document.getElementById("inpTxt").value;
str.toString();
str = str.split(" ");
for(var i = 0; i < str.length; i++)
{
arr.push(str[i]);
counter[i]++; //ignore that this array hasnt been properly declared yet, Im trying to make this equal length of arr with default value 0
//tried nested loop here for making comparison, didnt work
document.getElementById("print").innerHTML += "Total number of the word \"" + arr[i] + "\": " + counter[i] + " <br />";
}
}
If you're using ECMAScript2015(ES6), you can build a Set - which guarantees unicity - from your array :
var inputArray = [1, 1, 2, 3, 2, 4, 5, 5, 4, 1];
console.log(new Set(inputArray)) // displays Set { 1, 2, 3, 4, 5 }
Otherwise, you can loop over the array and check if a particular element follows another occurrence of itself :
var inputArray = [1, 1, 2, 3, 2, 4, 5, 5, 4, 1];
// with ES6 :
var result = inputArray.filter((element, index) => ! inputArray.slice(0, index).includes(element));
// without ES6 :
result=[];
for (var i=0; i<inputArray.length; i++) {
var currentElement = inputArray[i];
var previouslyFound = false;
for (var j=0; j<i && !previouslyFound; j++) {
previouslyFound = inputArray[i] == inputArray[j];
}
if (!previouslyFound) result.push(currentElement);
}
However, since we are looping over the array, it would be as fast to count the occurrences without unicizing the array first :
var inputArray = [1, 1, 2, 3, 2, 4, 5, 5, 4, 1];
// with ES6 :
var result = inputArray.reduce(function(map, element) {
map[element] = map.hasOwnProperty(element) ? map[element] + 1 : 1;
return map;
}, {});
// without ES6 :
var result = {};
for (var i=0; i<inputArray.length; i++) {
var currentElement = inputArray[i];
if (result.hasOwnProperty(currentElement)) {
result[currentElement] = result[currentElement] + 1;
} else {
result[currentElement] = 1;
}
}
Try the indexOf method of arrays to figure out whether you already have the string in array.
function gen()
{
var arr = [];
var counter = [];
var str = document.getElementById("inpTxt").value;
str.toString();
str = str.split(" ");
for(var i=0; i < str.length; i++)
{
if(arr.indexOf(str)==-1){
arr.push(str[i]);
counter[i]++; //ignore that this array hasnt been properly declared yet, Im trying to make this equal length of arr with default value 0
}
//tried nested loop here for making comparison, didnt work
document.getElementById("print").innerHTML += "Total number of the word \"" + arr[i] + "\": " + counter[i] + " <br />";
}
}
PS: please know that there are less expensive methods available out there but i am just trying to help with whatever i can.
Related
I am trying to make a function that takes in an array, and prints versions of the array with one number missing. For example, if the array were [1,2,3], it would print [2,3],[1,3], [1,2]. So I'm making a variable tempSeq, setting it equal to Sequence, printing it with Document.write(), and then resetting tempSeq to the original sequence. For some reason however, the variable sequence is being spliced. Not sure why this is happening, and any help would be appreciated!
function almostIncreasingSequence(sequence) {
var tempseq = sequence;
for (let i = 0; i < sequence.length; i++) {
tempseq = sequence;
tempseq.splice(i, 1);
document.write("(" + tempseq + ")");
}
return tempseq;
}
almostIncreasingSequence([10, 1, 2, 3, 4, 5]);
The function name is odd because ultimately the function is doing something else.
This line is actually saying 'call the "sequence" array also "tempseq"'
var tempseq = sequence;
and it is not saying 'clone the "sequence" array into "tempseq" (if you expect this behavior). Then splice actually operating on sequence array
tempseq.splice(i, 1); // equal to sequence.splice(i, 1)
Just clone the array:
// instead of
// var tempseq = sequence;
var tempseq = sequence.slice();
function almostIncreasingSequence(sequence) {
var tempseq = sequence.slice();
for (let i = 0; i < sequence.length; i++) {
tempseq = sequence;
tempseq.splice(i, 1);
document.write("(" + tempseq + ")");
}
return tempseq;
}
almostIncreasingSequence([10, 1, 2, 3, 4, 5]);
When you assign tempseq = sequence tempseq is still the same array, it is just a reference so splice effects both. Use reduce to create a copy of the array without the item at i
function almostIncreasingSequence(sequence) {
var tempseq = sequence;
for (let i = 0; i < sequence.length; i++) {
const tempseq = sequence.reduce((results, item, index) => index === i ? results : [...results, item], []);
document.write("(" + tempseq + ")");
}
return tempseq;
}
almostIncreasingSequence([10, 1, 2, 3, 4, 5]);
The array I get my original strings from looks something like this:
arr[0]:
11-3
12-6
arr[1]:
5-9
7-2
18-2
arr[2]:
2-7
(That's just an example, the general idea is that there can be any number of objects in arr and the string in each of them contains any number of #-# combos)
I'm trying to add all the numbers on the left together (if using the example above it would add something like 11, 12, 5, 7, 18, and 2 together) and store that number in a variable.
How would I go about this?
Edit 1: attempted code:
var winsLossNums = winLoss[0].match(/\d+/g).map(Number)
for (var i = 0; i < winLoss[0].match(/\d+/g).map(Number).length; i++) {
if (i % 2 === 0) {
totalNums.push(winLoss[0].match(/\d+/g).map(Number)[i]);
}
}
}
This code is in a loop, and every loop there is a new arr object like in the example above
Assuming your array values are strings with a new line between them, you can reduce over the array, split each value on \n and reduce again on that taking the first value of splitting on '-':
let arr = ['11-3\n12-6', '5-9\n7-2\n18-2', '2-7']
let tot = arr.reduce((a, c) => {
let pairs = c.split('\n')
return a + pairs.reduce((a, c)=> a + Number(c.split('-')[0]), 0)
}, 0)
console.log(tot)
console.log(11 + 12 + 5 + 7+ 18 + 2)
You might need to clean up data or split on whitespace if it's not cleanly one \n per line. But this should be a good start.
You can try this:
let arr = [
[
'11-3',
'12-6'
], [
'5-9',
'7-2',
'18-2'
], [
'2-7'
]
];
let sum = 0;
for (let index=0; index<arr.length; index++) {
let arrayMasterElement = arr[index];
// console.log(arrayMasterElement);
for (let index2=0; index2<arrayMasterElement.length; index2++) {
let arrayElement = arrayMasterElement[index2];
let elementArray = arrayElement.split('-');
let intVal = parseInt(elementArray[0]);
console.log('Int value: ' + intVal);
sum += intVal;
}
if (index == arr.length - 1) {
console.log('Sum: ' + sum);
}
}
how can I go through a list and make the computer check if it's a number, if it is a number, I want to count and move on until the end and then show the result.
for example if I had an array:
var myArray = [1,2,a,4];
What I did was I would first split my array:
var splitted = myArray.toString()split(",").join(" ");
and then I used the for loop to go through each splitted value and count it if it is a number(or a string) and then show the result in a the appropriate box:
for(i=0;i<splitted.length; i+=1)
{
if(isNaN(splitted[i])===true)
{
document.getElementById("resultWordCount").value = splitted[i];
}
else
{
document.getElementById("resultNumberCount").value = splitted[i];
but with this code I keep getting the last number that appears in my list and the last string that appears in my list to show up as a result in my boxes. What can I do to fix this?
You could check with isNaN and count.
var myArray = [1, 2, 'a', 4],
result = myArray.reduce(function (s, a) {
return s + !isNaN(a);
}, 0);
console.log(result);
var myArray = [1,2,a,4];
var result = 0;
for(var i=0; i < myArray.length; i++) {
result += !isNaN(+myArray[i]) ? myArray[i] : 0;
}
var count = 0;
myArray.forEach(function(item){
if(!isNaN(Number(item))){
count ++;
}
});
console.log(count);
first, if you already have an array, why would you transform it into a string, then split it, then join it again to another string? you're not looping over the array items but over the string characters. this will lead to all sorts of problems when your input changes.
then, isNaN(splitted[i])===true checks if the current item of the array is NOT a number, so you should ignore those instead of using them.
finally, you're not doing any sum anywhere, just assigning each item in turn to the value of the "resultNumberCount" tag. That's why, at the end of the process you just see whatever value was last in the array (or, actually, string)
You can use map function to count number of integers
var myArray = [1, 2, 'a', 4];
var numbers = 0;
myArray.map(function (a) {
if (Number(a))
numbers++;
});
console.log(numbers);
You can do:
var a = [1, 2, 'c', 4];
console.log(a.filter(function(value){
return !isNaN(value);
}).length)
You dont have to split your array
And just concatenate the values
var myArray = [1,2,"a",4];
var countNum = 0;
var countNaN = 0;
for(i=0;i<myArray.length; i+=1){
if(isNaN(myArray[i])){
document.getElementById("resultWordCount").value += myArray[i];
countNaN++;
}else{
document.getElementById("resultNumberCount").value += myArray[i];
countNum++;
}
}
console.log(countNaN);
console.log(countNum);
<input id="resultNumberCount" type="text" disabled >
<input id="resultWordCount" type="text" disabled >
EDIT:
If you want only the total:
var myArray = [1,2,"a",4];
var countNum = 0;
var countNaN = 0;
for(i=0;i<myArray.length; i+=1){
if(isNaN(myArray[i])){
countNaN++;
}else{
countNum++;
}
}
document.getElementById("resultNumberCount").value = countNum;
document.getElementById("resultWordCount").value = countNaN;
console.log(countNaN);
console.log(countNum);
<input id="resultNumberCount" type="text" >
<input id="resultWordCount" type="text" >
I have an application that takes in multiple arrays of data each or variable length. I plan on cycling through and displaying every combination of data for each array I'm given. My first inclination was to have a single number represent the state of each array since I know the number of combinations is the product of the number of elements of each array.
So for example:
A = [0,1,2,3]
B = [0,1,2,3]
C = [0,1]
So 4 x 4 x 2 = 32 combinations I need to represent
I've managed to represent all states by applying modulo and division to a given index using each array.length. My problem is that it doesn't order well (see snippet below). Has anyone solved a similar problem or know how I could change the algorithm to get it in order?
function multiArrayIndex(index, ...args) {
var arrays = args.slice();
var output = [];
for (var i = 0, curIndex = index; i < arrays.length; i++) {
var curArray = arrays[i];
var valueIndex =(curIndex % curArray.length);
output.push(curArray[valueIndex]);
curIndex = Math.ceil(curIndex / curArray.length);
}
return output;
}
demoP = document.getElementById("demo");
for(var i = 32; i>=1; i--){
demoP.innerHTML = demoP.innerHTML + i + " - " + multiArrayIndex(i, [0,1,2,3], [0,1,2,3], [0,1] ) + "<br />";
}
<p id="demo"></p>
Keeping the indices separate would be a nicer approach in my opinion.
Incrementing the indices could work kinda similar to how we added two numbers by hand in elementary school - if an index is too large, set it to zero and increment the next one by one:
var a = [0, 1, 2, 3]
var b = [0, 1, 2, 3]
var c = [0, 1]
var state = {
a: 0,
b: 0,
c: 0
}
function increment() {
state.a++;
if (state.a >= a.length) {
state.b++;
state.a = 0;
}
if (state.b >= b.length) {
state.c++;
state.b = 0;
}
if (state.c >= c.length) {
state.c = 0;
}
console.log(state);
}
console.log(state);
<button onclick='increment()'>Increment</button>
Updating the document based on the state should be trivial from here.
Sorry if this has already been asked but I did search "javascript sort index linked array" and found nothing satisfactory.
I've got an array of names, and another index linked array which records the frequency at which the names appear in a passage, and I want to sort both arrays not alphabetically but according to the name frequencies - say, most frequent to least frequent. I've got the following bit of code which does the job adequately, but I'm thinking that it looks like a hack. Surely there's a more decorous way to solve what must be a pretty common sorting problem.
I start with an array of names[] say, 6 Johns, 2 Annes, 9 Toms, 12 Andrews, 3 Kristens, 1 Archie, and 14 Peters - already sorted alphabetically and counted into frequencies, and the routine below results in an array of indexes to the names and frequency arrays which allows me to display the names and frequencies in order from highest to lowest.
var names = ["Andrew", "Anne", "Archie", "John", "Kristen", "Peter", "Tom"];
var frequency = [12, 2, 1, 6, 3, 14, 9];
var holder = [], secondpart = [], numindex = [];
var i;
for (i = 0; i < frequency.length; i++) {
if (frequency[i] < 10) {
holder[i] = "0" + frequency[i] + "!" + i; // add leading zeros as required
}
if (frequency[i] > 9) {
holder[i] = frequency[i] + "!" + i; // no leading zeros required
}
}
holder.sort();
holder.reverse();
for (i = 0; i < holder.length; i++) {
secondpart[i] = holder[i].substring(holder[i].indexOf("!") + 1, holder[i].length);
numindex[i] = parseInt(secondpart[i]);
}
I can now list both arrays according to the name frequencies.
var txt = "";
var useindex;
for (i = 0; i < numindex.length; i++) {
useindex = numindex[i];
txt = txt + names[useindex] + " - " + frequency[useindex] + "<br>";
}
Has anyone else had this problem and how did you solve it.
try this:
var names = ["Adam", "Peter", "Mahu", "Lala"];
var frequencies = [6,2,9,1];
var tupples=[];
for(let i = 0; i<names.length; i++)
{
tupples[i] = {
frequency : frequencies[i],
name : names[i]
};
}
//ascending
//tupples.sort(function(a,b){return a.frequency-b.frequency;});
//descending
tupples.sort(function(a,b){return b.frequency-a.frequency;});
for(let i=0; i<tupples.length; i++)
{
console.debug(tupples[i].name, tupples[i].frequency);
}
Basically you could use the indices and sort them by getting the the frequency for the given index.
var names = ['Andrew', 'Anne', 'Archie', 'John', 'Kristen', 'Peter', 'Tom'],
frequency = [12, 2, 1, 6, 3, 14, 9],
indices = names.map(function(_, i) { return i; });
indices.sort(function(a, b) {
return frequency[b] - frequency[a];
});
document.write('<pre>' + JSON.stringify(indices, 0, 4) + '</pre>');
document.write(indices.map(function(a) { return names[a]; }).join('<br>'));