Picking the largest number in an array - javascript

Write a single function that outputs the “largest” phone number in an input array (if multiple numbers are equally large, return the last one). Assume that the phone numbers are strings of 10 digits separated by dashes.
I wrote a function to answer the questions above. It comes out undefined. can someone help me find the error please. I feel that i am close to the answer.
var largestNumber = function(strings) {
var ints = strings.map(function(el) {
return el.replace(/-/g, '').split('').reduce(function(previousValue, currentValue, currentIndex, array) {
return previousValue + currentValue;
});
});
console.log(ints);
var largest = Math.max.apply(Math, ints);
return strings[ints.lastIndexOf(largest)];
};
console.log(largestNumber(['111-111-1111', '111-111-1112', '111-111-1113']));

ints.lastIndexOf(largest)
This part searches for the last occurence of largest in ints. However, largest will always be a number, but ints contains only strings. Therefore, the number isn’t found and undefined is returned. To fix this, convert largest back to a string:
ints.lastIndexOf(largest.toString())
Also, you don’t need to split the strings and concatenate them back together.
This code is working:
var largestNumber = function(strings) {
var ints = strings.map(function(el) {
return el.replace(/-/g, '');
});
console.log(ints);
var largest = Math.max.apply(Math, ints);
return strings[ints.lastIndexOf(largest.toString())];
};
console.log(largestNumber(['111-111-1111', '111-111-1112', '111-111-1113']));
Alternatively, you could map the strings to numbers:
var ints = strings.map(function(el) {
return Number(el.replace(/-/g, ''));
});

Since you are already using reduce() why not use one reduce() to return the highest
var largestNumber = function(strings) {
return strings.reduce(function(previousValue, currentValue) {
return +currentValue.replace(/-/g,'') >
+previousValue.replace(/-/g,'') ? currentValue : previousValue;
});
};
alert(largestNumber(['111-111-1111', '111-111-1112', '111-111-1113']));

Related

Iterate over two separate arrays of different length and populate a third using a condition in JavaScript?

I've done something similar in the past with a nested loop, but for some reason I can't get my mind around this to get it to work. I keep running into problems that involve indexing of two separate arrays and it's been a continual stumbling block
In this case, I'm trying to sort a string. The string includes letters and numbers, the task is to sort the letters in reverse alphabetical order while keeping the numbers at their same index.
I've come up with this solution (probably not the most efficient), but can't get the sortString array to come together so that I can join the letters and numbers back into a string.
function reverse(str) {
// split the str into an array
const arr = [...str]
// converts each element in arr to a number, letters are string 'NaN'
const numArray = arr.map(x=> Number(x)).map(x=> x >= 0 ? x : String(x))
// array of the sorted letters
const letters = arr.filter(x=> !/[0-9]/g.test(x)).reverse()
// initiate empty array to hold the combined numbers and letters
let sortString = []
// Use for loop to cycle through and replace elements that are 'NaN' with letters from the letter array. All pushed to sortString.
for (let i=0; i<arr.length; i++) {
sortString.push(numArray[i] === 'NaN' ? letters[0] : numArray[i])
}
return sortString
}
reverse("ab89c") // output should be "cb89a"
You could get an array of non digits, sort it and map the splitted string with the sorted letters in places if not a digit.
const
reverse = string => {
const
array = Array.from(string),
letters = array
.filter(v => /\D/.test(v))
.sort();
return array
.map(v => /\D/.test(v) ? letters.pop() : v)
.join('');
};
console.log(reverse("ab89c"));
A slightly different approach takes a Proxy for the wanted items of sorting:
How to sort only part of array? between given indexes
Here's code that works:
Explanation of how the code works is in-line as comments.
Basically it takes the numbers out, sorts the letters in reverse, and puts the sorted letters back in the right place.
Because it's step-by-step, you could add console log on each variable after it's assigned to see how it works step by step.
function reverse(input) {
// This function from: https://stackoverflow.com/a/32567789/569302
function testIsLetter(c) {
return c.toLowerCase() != c.toUpperCase();
}
// Convert from array to string to process character by character
let inputAsArray = input.split('');
// This is where we'll lookup where to put the letters when we're done
let mapped = inputAsArray.map((s) => {
return {
s,
isLetter: testIsLetter(s)
}
})
// Now that we've captured where the letters are, take the numbers (non-letters) out
let filtered = mapped.filter(m => m.isLetter)
// Convert the object into just letters so they're easily compared when we sort
let filteredAsLettersArray = filtered.map(f => f.s)
// Sort ascending
filteredAsLettersArray.sort()
// Reverse to sort descending
filteredAsLettersArray.reverse()
// Now we need to put the letters back.
let resultAsArray = [];
let letterIndex = 0;
mapped.forEach(m => {
// If it's a letter, we use the sorted result (incrementing letterIndex each time)
if (m.isLetter) {
resultAsArray.push(filteredAsLettersArray[letterIndex]);
letterIndex++;
} else {
// Otherwise we use the number
resultAsArray.push(m.s);
}
});
let result = resultAsArray.join('');
return result;
}
console.log(reverse("ab89c"));
console.log(reverse("1a2eb8f9c"));

Return count of duplicates

Here is the prompt: Write a function that will return the count of distinct case-insensitive alphabetic characters and numeric digits that occur more than once in the input string. The input string can be assumed to contain only alphabets (both uppercase and lowercase) and numeric digits.
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
Get all unique values in a JavaScript array (remove duplicates)
I used variances of the above questions/answers and tried to amend it for what I am looking for- the count of how many elements are found more than once
var arr = 'Indivisibilities';
var sorted_arr = arr.toLowerCase().split('').sort();
let count = 0;
let duplicateCount = (parm1) => {
for (var i = 0; i < sorted_arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
count ++;
}
} return count;
}
duplicateCount(arr);
Count returns 7, what is expected is 2. Also, I would really like to avoid using a for loop. I'm hoping this can be done with .forEach or something method. ** I'm still pretty knew to code so please try not to do any one liners :) I appreciate the efficiency, but I'm still trying to understand the logic
You can use reduce and filter
Change string to lowercase
Split string by ''
Use each element as key, if it is already present increase it's count by 1 else set it to 1
Filter values which are greater than 1 to see duplicates
Get length of filtered array
var str = 'Indivisibilities';
let duplicateCount = (str) => {
let dups = str.toLowerCase().split('').reduce((op,inp)=>{
op[inp] = op[inp] || 0
op[inp]++
return op
},{})
return Object.values(dups).filter(v=>v>1).length
}
console.log(duplicateCount(str));

Mapping and reducing new int array issues

var strings = [ '234-496-7459', '760-644-0201', '555-222-3333' ];
var ints = [];
console.log(strings);
strings.forEach(function(entry) {
var ints = entry.replace(/-/g, '');
console.log(ints);
});
var myResults = ints.map(function (el) {
return el.toString().split('').reduce(function (sum, b) {
return sum + +b;
}, 0);
});
console.log(myResults);
I have an array of strings that I want to take out the dashes then store the new arrays as ints. I am trying to reduce each array of ints to create a myResults that print out 53, 30, 33. I know there is something wrong with this code because the mapping and reduce doesn't want to work.
You need to push entry values in ints array after replace
var strings = [ '234-496-7459', '760-644-0201', '555-222-3333' ];
var ints = [];
strings.forEach(function(entry) {
ints.push(entry.replace(/-/g, ''));
});
var myResults = ints.map(function (el) {
return el.toString().split('').reduce(function (sum, b) {
return sum + +b;
}, 0);
});
alert(myResults);
You can combine your statements like this (in a working snipppet):
var strings = [ '234-496-7459', '760-644-0201', '555-222-3333' ];
var ints = strings.map(function(item) {
return item.replace(/-/g, '').split('').reduce(function(total, val) {
return total + +val;
}, 0);
});
document.write(JSON.stringify(ints));
Explanation:
You want to convert one array to another so use .map() not .forEach().
Then, right in the .map() callback, you can convert the string to total.
.replace(/-/g, '').split('') gets rid of the dashes and turns it into an array of letters.
.reduce() then runs on that array to sum up all the digits.
If you're looking for another way, you can use
Array#map, String#replace, String#split, Array#reduce with Arrow function syntax.
You can use RegEx /\d/g with String#match to get individual numbers as an array.
var ints = arr.map(el => el.match(/\d/g, '').reduce((sum, a) => sum + +a, 0));
\d matches a single digit. g is global flag, to get all the possible matches.
var arr = ['234-496-7459', '760-644-0201', '555-222-3333'];
var ints = arr.map(el => el.match(/\d/g, '').reduce((sum, a) => sum + +a, 0));
console.log(ints);
document.write(ints);
String#replace and String#split can also be used.
var ints = arr.map(el => el.replace(/-/g, '').split('').reduce((sum, a) => sum + +a, 0));
var arr = ['234-496-7459', '760-644-0201', '555-222-3333'];
var ints = arr.map(el => el.replace(/-/g, '').split('').reduce((sum, a) => sum + +a, 0));
console.log(ints);
document.write(ints);
Equivalent code in ES5
var ints = arr.map(function (el) {
return el.replace(/-/g, '').split('').reduce(function (sum, a) {
return sum + +a;
}, 0);
});
var arr = ['234-496-7459', '760-644-0201', '555-222-3333'];
var ints = arr.map(function(el) {
return el.replace(/-/g, '').split('').reduce(function(sum, a) {
return sum + +a;
}, 0);
});
console.log(ints);
Approach this in top-down fashion, step-by-step. For each step, we will write a little spec so we are perfectly clear on what we want to do. If we write the spec well, then the JS will follow easily.
We want to write a function sum_digits_of_array, for which the spec is:
sum_digits_of_array
Given an input array, return a new array, where each element is the sum of the digits of the corresponding element from the original array.
That is exactly the definition of map, so we can write:
function sum_digits_of_array(a) { return a.map(sum_digits); }
Now we just need to write sum_digits. We will also write a spec for that:
sum_digits
Given an input string, return the sum of the digits of the string.
That's easy enough:
function sum_digits(s) { return sum(digits(s)); }
Now for digits. Again we will write a little spec for ourselves:
digits
Given a input string, return array of individual digits, as numbers.
Instead of thinking of this as removing dashes and then splitting, we will use RegExp#match to just extract the digits:
function digits(s) { return s.match(/\d/g) . map(Number); }
Then
sum
Given an array of numbers, return the sum of all the numbers.
This is the definition of reduce, so
function sum(a) { return a.reduce(add); }
Then
add
Given two numbers, return the result of adding them
function add(a, b) { return a + b; }
That's it. So the entire solution, which is slightly more compact if we use ES6 arrow functions:
function sum_digits_of_array(a) {
const sum_digits = s => sum(digits(s));
const digits = s => s.match(/\d/g) . map(Number);
const sum = a => a . reduce(add);
const add = (a, b) => a + b;
return a . map(sum_digits);
}
Why code in this fashion? There are a number of good reasons.
You can read the code and tell what it's doing.
Related to that, it's easy to figure out where to modify the code if the problem changes.
We can easily test each little function to make sure it's working right.
The little functions we wrote might come in handy when solving a related problem, so we reduce the amount of work we have to do in the future.

Finding the sum of an array in javascript [duplicate]

This question already has answers here:
How to force JS to do math instead of putting two strings together [duplicate]
(11 answers)
Closed 7 years ago.
I have to write 6 small JavaScript scripts for school and I've got them all working apart from this one.
function calculate() {
var numbers = [
document.getElementById("num_one").value ,
document.getElementById("num_two").value ,
document.getElementById("num_three").value
];
var sum = numbers[0] + numbers[1] + numbers[2];
document.getElementById("display_sum").innerHTML = sum;
}
The user is supposed to enter 3 numbers click a button and it should add them all togther or "find the sum".
My Problem is, it just joins the numbers togther instead of adding them. Does anyone know a way to fix this?
You are "summing" string variables so Javascript is concatenating them.
You need to convert them to numbers in order to have an arithmetic sum:
function calculate() {
var numbers = [
document.getElementById("num_one").value ,
document.getElementById("num_two").value ,
document.getElementById("num_three").value
];
var sum = Number(numbers[0]) + Number(numbers[1]) + Number(numbers[2]);
document.getElementById("display_sum").innerHTML = sum;
}
Parse string using parseFloat(), parseInt() or Number(), for converting it's to number. Otherwise + will just do string concatenation , since the values are string.
function calculate() {
var numbers = [
document.getElementById("num_one").value,
document.getElementById("num_two").value,
document.getElementById("num_three").value
];
var sum = parseFloat(numbers[0]) + parseFloat(numbers[1],) + parseFloat(numbers[2]);
document.getElementById("display_sum").innerHTML = sum;
}
function calculate() {
var numbers = [
document.getElementById("num_one").value,
document.getElementById("num_two").value,
document.getElementById("num_three").value
];
var sum = Number(numbers[0]) + Number(numbers[1]) + Number(numbers[2]);
document.getElementById("display_sum").innerHTML = sum;
}
function calculate() {
var numbers = [
document.getElementById("num_one").value,
document.getElementById("num_two").value,
document.getElementById("num_three").value
];
var sum = parseInt(numbers[0], 10) + parseInt(numbers[1], 10) + parseInt(numbers[2], 10);
document.getElementById("display_sum").innerHTML = sum;
}
The value property is string. In order to use it in arithmetic operations, you need to parse it to integers. The simpliest way to do this in JS is +x. You can use Array.prototype.map and Array.prototype.reduce to make it easier:
var ids = ['num_one', 'num_two', 'num_three'];
var sum = ids
.map(function(x) { return +document.getElementById(x).value; })
.reduce(function(a,b) { return a+b; }, 0);
With this way, you will be able to introduce new elements into calculations with minimal changes.
.value return String you need convert it to Number,
you can do it with parseInt or parseFloat(if you have float values), or with Number() or just add + before value
var numbers = [
+document.getElementById("num_one").value,
+document.getElementById("num_two").value,
+document.getElementById("num_three").value
];
or
var numbers = [
Number(document.getElementById("num_one").value),
Number(document.getElementById("num_two").value),
Number(document.getElementById("num_three").value)
];
or
var numbers = [
parseInt(document.getElementById("num_one").value, 10),
parseInt(document.getElementById("num_two").value, 10),
parseInt(document.getElementById("num_three").value, 10)
];
The shortest approach is to use Array.prototype.map
The map() method creates a new array with the results of calling a provided function on every element in this array.
in combination with Number
The Number JavaScript object is a wrapper object allowing you to work with numerical values. A Number object is created using the Number() constructor.
The primary uses for the Number object are:
If the argument cannot be converted into a number, it returns NaN.
In a non-constructor context (i.e., without the new operator), Number can be used to perform a type conversion.
and then Array.prototype.reduce
The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
in combination with a callback like
function (a, b) {
return a + b;
}
Together in a single line with your code wrapped:
function calculate() {
var numbers = [
document.getElementById("num_one").value,
document.getElementById("num_two").value,
document.getElementById("num_three").value
],
sum = numbers.map(Number).reduce(function (a, b) { return a + b; });
document.getElementById("display_sum").innerHTML = sum;
}
A scalable solution in one line of es6:
var sum = numbers.reduce((a, b) => Number(a) + Number(b), 0);
Be sure to include an initialValue at the end there - it'll guarantee the callback is executed and a number is returned in cases where the array contains no values/one value.
More info on reduce
Depending on whether your input numbers are integers or decimals, you can use parseInt or parseFloat.
There are already plenty of reasonable answers, but here's a neat shorthand alternative:
var sum = +numbers[0] + +numbers[1] + +numbers[2];
I think you can use an array to store the inputs like
<script>
var numbers;
function push(){
numbers.push(getDocumentById("someid").val;
}
function calculate(){
var sum=0;
for(i=0; i<numbers.len; i++){
sum=sum + numbers[i];
}
alert(sum);
}
</script>
<div>
<button id="someid" value=20 onClick="addToArray();">click to push</button>
</div>
<div>
<button id="calc" onClick="calculate();">click to calculate</button>
</div>
The following will solve the problems:
function calculate() {
var numbers = [
+(document.getElementById("num_one").value) ,
+(document.getElementById("num_two").value) ,
+(document.getElementById("num_three").value)
];
var sum = numbers[0] + numbers[1] + numbers[2];
document.getElementById("display_sum").innerHTML = sum;
}
By default, javascript treats input values as strings. So you have to manually convert them to integers like this:
var numbers = [
document.getElementById("num_one").value ,
document.getElementById("num_two").value ,
document.getElementById("num_three").value
];
document.getElementById("display_sum").innerHTML =
numbers
.reduce(function(sum, element) { return sum + parseInt(element, 10);}, 0);
What is good about this code, is that if you need to calculate for more than three elements you only need to modify your numbers array.

Return the index and array after reduced

I am playing with reduce method provided by mozilla. Underscore provides its own version which seems very similar. Reducing an array is very simple.
ArrayName.reduce(function(a,b) {
return a +b;
});
I use a very similar approach when sorting arrays as well. However, what I do not understand is how to return a list of calls. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce Provides a really cool table that shows how their method works. I set my array pretty much the same
var array = [1,2,3,100,55,88,2];
var sortArray= function(a,b) {
return a -b;
}
var sorted = array.sort(sortArray);
var reduced = sorted.reduce(function(previousValue,currentValue, index,array){
return previousValue + currentValue;
});
What I wanted to set up though was each call that was made. I figured that I could simply reference the index in the return value with a , at the end.
return previousValue + currentValue, index;
However, that only returns the index. I am trying to figure a way to get the value of each call. Does this approach allow you to get each call?
You don't need to use reduce for what you are doing. Try
function running_total(array) {
var sum = 0;
return array.map(function(elt) {
return sum += elt;
};
}
Reduce is about "boiling down" an array to a "single thing". In contrast, map is about "transforming" elements of the array. Your problem (as I understand it) is to transform each element of the array into the sum of itself and all the preceding elements. Therefore, conceptually, it's a map, not a reduce.
Using the , in the return statement will only return index due to the comma operator rule
[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, index, array) {
console.log(previousValue+"--"+currentValue)
return previousValue + currentValue;
});
this will do want you want
You can create another array and store its value for each progress.
var array = [1,2,3,100,55,88,2];
var sortArray= function(a,b) {
return a -b;
}
var sorted = array.sort(sortArray);
var progress = [];
var reduced = sorted.reduce(function(previousValue,currentValue, index,array){
progress[index] = previousValue + currentValue;
return progress[index];
}, 0);
// ^^^^^
// give it a init value so it starts at first element.
console.log(progress);
However, as torazaburo says, as you expect to get an array, you should use .map which returns an array instead of .reduce.

Categories

Resources