I am trying to write a function that takes in an array and a max cutoff number. The number is the max number that the string can contain, and this number replaces all array elements greater than the number. For example, if the array is [1,2,3,4,5,6] and the cutoff number is 4, the output should be [1,2,3,4,4,4].
This is what I have so far, but I am only getting [1,2,3,4,5] as the output instead of [1,2,3,3,3]. Any suggestions??
var maxCutoff = function(array, number) {
for (var i=0; i<array.length; i++) {
if (array.indexOf(i) > number) {
array.pop();
array.push(number);
return array;
} else if (array.indexOf(i) <= number) {
return array;
}
}
}
console.log(maxCutoff([1,2,3,4,5], 3));
You can deal with it with a simple one-liner, using Array#map.
const maxCutoff = (arr, num) => arr.map(v => v > num ? num : v);
console.log(maxCutoff([1,2,3,4,5], 3));
You could use a ternary for the result for mapping.
const maxCutoff = (array, value) => array.map(a => a > value ? value : a);
console.log(maxCutoff([1, 2, 3, 4, 5], 4));
or Math.min for the result for mapping.
const maxCutoff = (array, value) => array.map(a => Math.min(a, value));
console.log(maxCutoff([1, 2, 3, 4, 5], 4));
The solution is quite simple, you just need to change the element to max.
Assuming you are a beginner to JS, the below solution should be more comprehendable to you. Another answer that uses map, might come off as magical, that should be more efficient, but it depends on how well the browser handles the map function, for most cases, browsers do implement it quite fine
var maxCutoff = function(array, number) {
for (var i=0; i<array.length; i++) {
if(array[i]>number)
array[i] = number;
}
return array
}
console.log(maxCutoff([1,2,3,4,5], 3));
Related
I was trying to write a algorithm in javascript that returns all the possible 3 digit numbers numbers from a given array of length 6
For Example
var arr = [1, 2, 3, 4, 5, 6];
I have already got the combinations with the same sets of numbers in different positions in the 2D array.
(The code which I took the help of)
If I have the same numbers in different combinations then I would like to remove them form the array. like I have [1, 2, 3] at index i in the array comtaining all the possible combinations then I would like to remove other combination with the same numbers like [2, 1, 3], [1, 3, 2] and so on..
Note the array also contains numbers repeated like [3, 3, 3], [2, 2, 2], [3, 2, 3] and so on
I expect an 2d array which has the values : [[1,2,3],[1,2,4],[1,2,5],[1,2,6],[1,3,4]] and so on (24 possibilities)
Is there any way to do this?
Extending the answer you linked, just filter out the results with the help of a Set.
Sort an individual result, convert them into a String using join(), check if it's present in set or not, and if not, then store them in the final result.
function cartesian_product(xs, ys) {
var result = [];
for (var i = 0; i < xs.length; i++) {
for (var j = 0; j < ys.length; j++) {
// transform [ [1, 2], 3 ] => [ 1, 2, 3 ] and append it to result []
result.push([].concat.apply([], [xs[i], ys[j]]));
}
}
return result;
}
function cartesian_power(xs, n) {
var result = xs;
for (var i = 1; i < n; i++) {
result = cartesian_product(result, xs)
}
return result;
}
function unique_cartesian_power(xs, n) {
var result = cartesian_power(xs, n);
var unique_result = [];
const set = new Set();
result.forEach(function(value) {
var representation = value.sort().join(' ');
if (!set.has(representation)) {
set.add(representation);
unique_result.push(value);
}
});
return unique_result;
}
console.log(unique_cartesian_power([1, 2, 3, 4, 5, 6], 3));
const arr = [1, 2, 3, 4, 5, 6];
const result = arr.reduce((a, v) => arr.reduce((a, v2) => {
arr.reduce((a, v3) => {
const current = [v, v2, v3].sort().join(",");
!a.find(_ => _.sort().join() === current) && a.push([v, v2, v3]);
return a;
}, a);
return a;
}, a), []);
console.log(result.length);
console.log(...result.map(JSON.stringify));
You could take an iterative and recursive approach by sorting the index and a temporary array for the collected values.
Because of the nature of going upwards with the index, no duplicate set is created.
function getCombination(array, length) {
function iter(index, right) {
if (right.length === length) return result.push(right);
if (index === array.length) return;
for (let i = index, l = array.length - length + right.length + 1; i < l; i++) {
iter(i + 1, [...right, array[i]]);
}
}
var result = [];
iter(0, []);
return result;
}
var array = [1, 2, 3, 4, 5, 6],
result = getCombination(array, 3);
console.log(result.length);
result.forEach(a => console.log(...a));
.as-console-wrapper { max-height: 100% !important; top: 0; }
This is a good example, that it is usually worthwhile not asking for a specific answer for a generic problem shown with a specific question; however as you've requested - if you really have the above constraints which kind of don't make much sense to me, you could do it like that:
function combine(firstDigits, secondDigits, thirdDigits) {
let result = [];
firstDigits.forEach(firstDigit => {
// combine with all secondDigitPermutations
secondDigits.forEach(secondDigit => {
// combine with all thirdDigitPermutations
thirdDigits.forEach(thirdDigit => {
result.push([firstDigit, secondDigit, thirdDigit])
})
})
});
// now we have all permutations and simply need to filter them
// [1,2,3] is the same as [2,3,1]; so we need to sort them
// and check them for equality (by using a hash) and memoize them
// [1,2,3] => '123'
function hashCombination(combination) {
return combination.join('ಠ_ಠ');
}
return result
// sort individual combinations to make them equal
.map(combination => combination.sort())
.reduce((acc, currentCombination) => {
// transform the currentCombination into a "hash"
let hash = hashCombination(currentCombination);
// and look it up; if it is not there, add it to cache and result
if (!(hash in acc.cache)) {
acc.cache[hash] = true;
acc.result.push(currentCombination);
}
return acc;
}, {result: [], cache: {}})
.result;
}
console.log(combine([1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]).length);
console.log(...combine([1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]).map(JSON.stringify));
This does not include some super-clever assumptions about some index, but it does abuse the fact, that it's all about numbers. It is deliberately using no recursion, because this would easily explode, if the amount of combinations is going to be bigger and because recursion in itself is not very readable.
For a real world problem™ - you'd employ a somewhat similar strategy though; generating all combinations and then filter them. Doing both at the same time, is an exercise left for the astute reader. For finding combinations, that look different, but are considered to be the same you'd also use some kind of hashing and memoizing.
let arr1 = [1,2,3,4,5,6];
function getCombination(arr){
let arr2 = [];
for(let i=0; i<arr.length; i++){
for(let j=i; j<arr.length; j++){
for(let k=j; k<arr.length; k++){
arr2.push([arr[i],arr[j],arr[k]]);
}
}
}
return arr2;
}
console.log(getCombination(arr1));
I'm trying to solve this task of finding the unique element inside an array.
So far I managed to solve 95%, but I'm failing on 0. I get an error saying that expected 0 and got 1.
I should get //10, which it does, but after I'm failing the test online. For all other values it has passed.
Any ideas about how to solve this and what I'm missing here?
function findOne(arr) {
let x = arr[0];
for (let i of arr) {
if (i === x) {
continue;
} else {
x = i;
}
return x;
}
}
console.log(findOne([3, 10, 3, 3, 3]));
I don't really understand your code. You start with the first value in the array, then you loop through the array, skipping anything that's the same, and then return the first one that's not the same. That won't find unique values, it'll just find the first value that doesn't equal the first value. So for instance, try it on the array [1,2,2,2,2] and you'll get a result of 2 instead of 1, even though that's clearly wrong.
Instead, you can create a map of each value and its incidence, then filter by the ones that equal 1 at the end.
function findOne(arr) {
const incidences = arr.reduce((map, val) => {
map[val] = (map[val] || 0) + 1;
return map;
}, {});
const values = Object.keys(incidences);
for (let i = 0; i < values.length; ++i) {
if (incidences[values[i]] === 1) { return values[i]; }
}
return null;
}
EDIT The above won't preserve the type of the value (i.e. it'll convert it to a string always, even if it was originally a number). To preserve the type, you can use an actual Map instead of an object:
function findOne(arr) {
const incidences = arr.reduce((map, val) => {
map.set(val, (map.get(val) || 0) + 1);
return map;
}, new Map());
const singletons = Array.from(incidences).filter(entry => entry[1] === 1);
return singletons.map(singleton => singleton[0]);
}
Consider the following:
Recall that a span = max - min + 1;
Let Partition P1 be span from 0..span-1;
Let Partition P2 be span from span..(2*span)-1:
Place a number in P1 if it is not in P2.
Place a number in P2 if it is already in P1.
Once the number is in P2, do not consider it again.
If a number is in P1 then it is unique.
You can get all values that appear once, by using a map to count how many times each element has appeared. You can then reduce that map into an array of unique values:
const findUnique = arr => {
const mapEntries = [...arr.reduce((a, v) => a.set(v, (a.get(v) || 0) + 1), new Map()).entries()]
return mapEntries.reduce((a, v) => (v[1] === 1 && a.push(v[0]), a), [])
}
console.log(findUnique([3, 10, 3, 3, 3]))
console.log(findUnique([1, 2, 3, 2, 4]))
console.log(findUnique([4, 10, 4, 5, 3]))
If you don't care about multiple unique values, you can just sort the array and use logic, rather than checking every value, provided the array only contains 2 different values, and has a length greater than 2:
const findUnique = arr => {
a = arr.sort((a, b) => a - b)
if (arr.length < 3 || new Set(a).size === 1) return null
return a[0] === a[1] ? a[a.length-1] : a[0]
}
console.log(findUnique([3, 10, 3, 3, 3]))
console.log(findUnique([3, 3, 1]))
console.log(findUnique([3, 1]))
console.log(findUnique([3, 3, 3, 3, 3]))
Your code is complex, Try this
function findOne(arr) {
const uniqueItems = [];
arr.forEach(item => {
const sameItems = arr.filter(x => x === item);
if (sameItems.length === 1) {
uniqueItems.push(item);
}
});
return uniqueItems;
}
console.log(findOne([0, 1, 1, 3, 3, 3, 4]));
I'm getting all unique items from passed array, It may have multiple unique item
this is a way simpler and fast:
function findOne(arr) {
const a = arr.reduce((acc, e) => {
e in acc || (acc[e] = 0)
acc[e]++
return acc
}, {})
return Object.keys(a).filter(k => a[k] === 1)[0] || null
}
I'm trying to find the second largest number in an array of numbers, but the greatest number appears twice, so I can't just remove it from the array and select the new highest number.
array = [0, 3, 2, 5, 5] (therefore 3 is the 2nd largest value)
I have this code where I can explicitly return 3, but it wouldn't work on other arrays:
function getSecondLargest(nums) {
var sorted_array = nums.sort(function (a,b) {return a - b;});
var unique_sorted_array = sorted_array.filter(function(elem, index, self) {
return index === self.indexOf(elem);
})
return unique_sorted_array[unique_sorted_array.length - 2];
}
return unique_sorted_array[unique_sorted_array.length - 2];
If I wanted to make it more dynamic, is there a way that I could identify the greatest value of the array, then compare that against each iteration of the array?
I was thinking that something along the lines of:
var greatestNum = sortedArray[-1]
while(greatestNum != i) do {
//check for the first number that doesn't equal greatestNum
}
Any help would be appreciated.
You can simply create a Set first and than sort in descending and take the 1st index element
let array = [0, 3, 2, 5, 5]
let op = [...new Set(array)].sort((a,b) => b-a)[1]
console.log(op)
For those who thinks in terms of efficiency. this is the best way IMO
let array = [0, 3, 2, 5, 5]
let max = -Infinity
let secondMax = -Infinity
for(let i=0; i<array.length; i++){
if(array[i] > max){
secondMax = max
max = array[i]
}
}
console.log(secondMax)
I’d recommend doing something more like
const nums = [0, 3, 2, 5, 5];
nums.sort(function (a,b) {return b - a;})
for (let i = 1; i < nums.length; i++) {
if (nums[0] !== nums[i]) {
return nums[i];
}
}
which should be a lot more efficient (especially in terms of memory) than converting to a set and back...
Try this:
var intArray = stringArray.map(nums); // now let's sort and take the second element :
var second = intArray.sort(function(a,b){return b-a})[1];
};
For those who wants to do this using Math.max(). Here's the simplest way to do this.
const getSecondLargest = function (arr) {
const largest = Math.max.apply(null, arr);
for (let i = 0; i < arr.length; i++) {
if (largest === arr[i]) {
arr[i] = -Infinity;
}
}
return Math.max.apply(null, arr);
};
console.log(getSecondLargest([3, 5, 9, 9, 9])); //5
Side note: Math.max() don't take an array, so we have to use Math.max.apply() to pass the array in the function. -Infinity is smaller than any negative finite number.
There is an array and I want to use foreach loop to get the biggest number
Here is an array
const array2 = ['a', 3, 4, 2]
What i try in JS:
function biggestNumberInArray3(arr) {
var largest = arr[0] || null;
var number = null;
arr.forEach (value => {
number = value
largest = Math.max(largest, number);
})
return largest;
}
Looks like Math.max isn't work in here.
It returns NaN
Are there any other ways to use foreach loop to compare the elements in an array?
P.S.: this foreach loop will return 4
forEach don't return any value.
You can use Filter and Math.max
use filter to remove all non-number values.
use Math.max to get highest value.
const array2 = ['a', 3, 4, 2]
console.log(Math.max(...array2.filter(e=> !isNaN(e))))
You should use Array.reduce to find the max number and filter it before the max operation as the presence of a will cause the result to be a NaN.
const array2 = ['a', 3, 4, 2]
var max = array2.filter((num)=> !isNaN(num)).reduce((a, b)=>{
return Math.max(a, b);
});
console.log(max);
const array2 = ['a', 3, 4, 2]
var max = Math.max(...array2.filter(num => Number.isInteger(num)));
console.log(max);
If you want to use forEach , you can just add a check for numbers in your code
function biggestNumberInArray3(arr) {
var largest = null;
var number = null;
arr.forEach (value => {
if(typeof(value) === "number"){
number = value
largest = Math.max(largest, number);
}
})
return largest;
}
console.log(biggestNumberInArray3(['a', 3, 4, 2]))
Here you have another solution using only reduce():
const array2 = ['a', 3, 4, 2, "hello", {hello:"world"}];
let res = array2.reduce((max, e) => isNaN(e) ? max : Math.max(max, e), null);
console.log(res);
Remove the string from array, see demo. Not interested in efficient and simple code? forEach() only returns undefined so you'll need to get a side-effect in order to get any result. In the demo below there's a variable outside the loop that changes as the loop progresses. Eventually this variable will be the greatest number in the array.
Demo
/*
Math.max.apply()
======================================*/
const array = ['a', 3, 4, 2];
//Get rid of the string
const num = array.shift();
console.log(`Math.max.apply({}, arr) ========= ${Math.max.apply({}, array)}`);
/*
forEach()
=======================================*/
let max = 0;
array.forEach(num => {
max = num > max ? max = num : max;
});
console.log(`array.forEach() ================ ${max}`);
I have an array:
var data = [0,1,2,3,4,5];
that I would like to splice into [0,1,2] and [3,4,5] followed by averaging it so the final result would be:
var dataOptimised = [1,4];
this is what I have found so far:
function chunk (arr, len) {
var chunks = [];
var i = 0;
var n = arr.length;
while (i < n) {
chunks.push(arr.slice(i, i += len)); // gives [[0,1,2] [3,4,5]]
}
return chunks;
};
How to reduce it?
Thanks
Sum each chunk using Array.reduce() and divide by the chunk's length.
var data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30];
function chunkAverage(arr, len) {
var chunks = [];
var i = 0;
var n = arr.length;
var chunk;
while (i < n) {
chunk = arr.slice(i, i += len);
chunks.push(
chunk.reduce((s, n) => s + n) / chunk.length
);
}
return chunks;
};
console.log(chunkAverage(data, 3));
You can map the array and reduce it.
function chunk(arr, len) {
var chunks = [];
var i = 0;
var n = arr.length;
while (i < n) {
chunks.push(arr.slice(i, i += len)); // gives [[0,1,2] [3,4,5]]
}
return chunks;
};
var data = [0, 1, 2, 3, 4, 5];
var result = chunk(data, 3).map(o => (o.reduce((c, v) => c + v, 0)) / o.length);
console.log(result);
Split the array in half using splice. And use .reduce to take sum and average finally
var arrR = [0, 1, 2, 3, 4, 5],
arrL = arrR.splice(0, Math.ceil(arrR.length / 2)),
results = [getAverave(arrL), getAverave(arrR)];
console.log(results)
function getAverave(arr) {
return arr.reduce(function(a, b) {
return a + b;
}) / arr.length;
}
Here is the sortest answer possible for this question.
n is the index you want to slice from.
function chunk (arr, n) {
return [Math.sum.apply(null, arr.slice(0, n)), Math.sum.apply(null, arr.slice(n, arr.length))];
};
If you don't mind using underscore.js, you can use the _.chunk() function to easily chunk your array, then map() each chunk to a reduce() function which averages each chunk.
When importing the underscore.js library, you can reference the library using the _ symbol.
const arr = [0, 1, 2, 3, 4, 5];
const len = 3;
const result = _.chunk(arr, len).map(chunk => chunk.reduce((a, b) => a + b, 0) / chunk.length);
console.log(result); // Outputs [1, 4]
If you have an odd-length array; say that arr = [0, 1, 2, 3, 4, 5, 6], then result would be [1, 4, 6].
In HTML, you can include the library in a <script> tag:
<script src="http://underscorejs.org/underscore.js"></script>
Here's a working jsfiddle where you can see it in action (you'll have to open the F12 tools to see console output; the StackOverflow embedded snippets are kind of funky and don't work right).
Agreeing with both Ori Drori and Eddie, but I thought I might also provide some additional minor changes to your chunk function for consistency and maintainability's sake...
When writing JavaScript, I would recommend using function names that won't collide with common/expected variable names. For example, with a function like chunk() that returns a "chunk", it's likely you would want to create a variable called chunk to hold its return value. A line of code like var chunk = chunk() is an obvious problem, but if it gets any less direct it can easily wreak havoc down the line. Using the const var = function pattern (see snippet) helps you avoid writing over the original function by throwing an error on the correct line, but I would argue it's also still good to get in the habit of using a naming convention that doesn't have this drawback just in case you can't use something like const. My approach is to always include a verb in the function name. In your case, "chunk" can also be considered a verb, but it conflicts. So, I prefixed it with "get".
const getChunk = (arr, len) => {
const chunks = []
const n = arr.length
let i = 0
while (i < n) {
chunks.push(arr.slice(i, i += len))
}
return chunks
}
const data = [0,1,2,3,4,5]
const optimizedData =
getChunk(data, 3).map(chunk =>
chunk.reduce((total, val) => total + val) / chunk.length
)
console.log(optimizedData)