Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 5 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Improve this question
I have a JSON dataset,
{
"a": ["73.0", "41.0", "98.0", "43.0"],
"s": ["74.0", "43.0", "112.0", "44.0"],
"f": ["75.0", "45.0", "116.0", "45.0"],
"l": ["76.0", "47.0", "120.0", "46.0"],
"x": ["77.0", "49.0", "128.0", "47.0"],
"q": ["78.0", "51.0", "134.0", "48.0"]
}
I want to closest match with a test data e.g. below, closest match is the array in the dataset which has lowest average difference related to the test array. In this example the closest match is "a": ["73.0", "41.0", "98.0", "43.0"],
{
"t": ["75.0", "42.0", "100.0", "44.0"]
}
Any library which can help with this? btw doing in JS.
This answer is based on the assumption that:
Your json is parsed and normalized so that all array values are numbers
You intend to measure difference in absolute numbers: diff(a, b) => Math.abs(a - b)
You want to find the key of the property pointing to the array that matches closest
// We're gonna get the closest match from here
const parsedJson = {
a: [73, 41, 98, 43],
s: [74, 43, 112, 44],
f: [75, 45, 116, 45],
l: [76, 47, 120, 46],
x: [77, 49, 128, 47],
q: [78, 51, 134, 48],
};
// We're gonna find the closest match to this
const comparator = [75, 42, 100, 44];
// Gets the average value of all given numbers
const avg = (...numbers) => numbers.reduce((acc, n) => acc + n, 0) / numbers.length;
// Returns an array with the absolute numeric difference
// between corresponding indices within 2 given arrays of
// numbers.
const difference = (arr1, arr2) => arr1.map((num, i) => Math.abs(num - arr2[i]));
// Returns the key of source that contains the array that
// matches closest to predicate.
const closestMatch = (comparator, source) => {
const [keyOfClosestMatch] = Object
.keys(source)
.map(key => [key, avg(...difference(comparator, source[key]))] )
.reduce((lowestSoFar, nextPredicate) => {
return lowestSoFar[1] < nextPredicate[1]
? lowestSoFar
: nextPredicate;
});
return keyOfClosestMatch;
}
let closestKey = closestMatch(comparator, parsedJson);
document.body.innerText = `Closest: "${closestKey}": [${parsedJson[closestKey]}]`;
You could iterate the keys and the items and check the absolute difference for taking the closest value for the result array.
var data = { a: ["73.0", "41.0", "98.0", "43.0"], s: ["74.0", "43.0", "112.0", "44.0"], f: ["75.0", "45.0", "116.0", "45.0"], l: ["76.0", "47.0", "120.0", "46.0"], x: ["77.0", "49.0", "128.0", "47.0"], q: ["78.0", "51.0", "134.0", "48.0"] },
test = ["75.0", "42.0", "100.0", "44.0"],
result = Object.keys(data).reduce(function (r, k, j) {
data[k].forEach(function (a, i) {
if (!j || Math.abs(a - test[i]) < Math.abs(r[i] - test[i])) {
r[i] = a;
}
});
return r;
}, []);
console.log(result);
Related
This question already has answers here:
How to remove all the odd indexes (eg: a[1],a[3]..) value from the array
(7 answers)
Closed 8 months ago.
I have an array as shown below, containing 6 numbers. I'm trying to create a function that deletes a value if it's an even/odd occurance. For example, if I type the function deleteData(myArr,"even"), it will remove data number 0th, 2nd, and 4th. And the other way around if it's "odd". But when I tried running my code, it didn't work the way i wanted it to go. Can anybody tell me why?
const myArr=[90,34,28,19,26,22];
function deleteData (array,occuranceType){
switch (occuranceType){
case "odd":
for (let i=0;i<array.length;i++){
if (i%2!==0){
array.splice(i,1);
};
};
break;
case "even":
for (let i=0;i<array.length;i++){
if (i%2==0){
array.splice(i,1);
};
};
break;
};
};
deleteData(arr,"odd")
console.log(arr)
This is the result in the console : [ 90, 28, 19, 22 ]
You can use filter for this since it's easier and you don't mutate the original array.
let myArr = [90, 34, 28, 19, 26, 22];
function deleteData(array, removeEven) {
return array.filter((v, i) => removeEven ? (i % 2 !== 0) : (i % 2 === 0));
};
myArr = deleteData(myArr, true)
console.log(myArr)
You can filter the array based on the pos argument passed to the function.
const deleteData = (array, pos) =>
array.filter((_, i) => i % 2 === Number(pos !== "even"));
console.log(deleteData([90, 34, 28, 19, 26, 22], "odd"));
console.log(deleteData([90, 34, 28, 19, 26, 22], "even"));
Note: Number(false) returns 0 and Number(true) returns 1.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have string like
var t = 'red: 5, purple: 7, fuchsia: 10, green: 8';
I want to make array like
a = ['red', 'purple', 'fuchsia', 'green'];
b = [ 5, 7, 10, 8]
Please help me
Sample solution:
const t = 'red: 5, purple: 7, fuchsia: 10, green: 8';
const tarr = t.split(', ');
const a = [];
const b = [];
for (const item of tarr) {
const [k, v] = item.split(': ');
a.push(k);
b.push(~~v); // '~~' is a shortcut to convert string value to number
}
console.log(a, b);
I am trying to do a basic binary search for a value in an array using the recursion method. I used the Iterative method on this same array and got the right output. But this code is returning false (element is not in the array) regardless of whether the input is in the array or not.
let recursionFunction = function (arr, x, start, end) {
if (start > end) {
return false
}
let mid = Math.floor((start + end)/2)
if (arr[mid] == x) {
return true
}
if (arr[mid] > x) {
return recursionFunction(arr, x, start, mid-1)
} else {
return recursionFunction(arr, x, mid+1, end)
}
}
let x = 91
let arr = [28, 91, 30, 33, 2, 7, 88, 90, 70, 44, 40, 41]
if (recursionFunction(arr, x, 0, arr.length-1)) {
console.log("element is found in arr")
} else {
console.log('element is not found in arr')
}
as stated in the comments, your array should be ordered in order to the binary search to work, think of the steps for your provided array ([28, 91, 30, 33, 2, 7, 88, 90, 70, 44, 40, 41])
in the first step it will take the value in the middle of the array (7) which will be lower than the value that you look (91) then it will reduce your array to ([88, 90, 70, 44, 40, 41]) and then you can notice why your item is not found.
using sort in front of your array fixes the issue :)
5 7
8 70
10 40
11 41
element is not found in arr
let recursionFunction = function (arr, x, start, end) {
if (start > end) {
return false
}
let mid = Math.floor((start + end)/2)
console.log(mid, arr[mid])
if (arr[mid] == x) {
return true
}
if (arr[mid] > x) {
return recursionFunction(arr, x, start, mid-1)
} else {
return recursionFunction(arr, x, mid+1, end)
}
}
let x = 91
// with sort, it will work.
let arr = [28, 91, 30, 33, 2, 7, 88, 90, 70, 44, 40, 41].sort();
if (recursionFunction(arr, x, 0, arr.length-1)) {
console.log("element is found in arr")
} else {
console.log('element is not found in arr')
}
Your array needs to be sorted for a binary search. It checks to see if 91 is in the middle, no then since 91 is greater than 7, it checks [mid+1, end].
You just have to sort your array before performing the binary search. So on line 16 where you create your example data just add .sort() to the end.
Binary search isn't possible with an unsorted data set.
I assume you're doing this just for the sake of learning but I want to point out that most programming languages will use binary search under the hood if your list is sorted and you perform a find. Which is why it's important to understand it as a concept but it would be incredibly unlikely you'd ever have to implement it yourself.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Lets say you use indexOf on an array to find all cases that say apple. If it comes back with three cases at positons 1, 2 and 3.
Now lets say there is an array = [10, 20, 30 ,40 ,50 ,60 ,70 ,80 ,90 ,100]
is there a way to use them cases 1,2 and 3 which come to 6. So is there a a way to go to position 6 "70" and produce that number. Depending on what the indexOf provides, is there a way to select that number from the array. Also if the indexOF produced 3.5 would there be a way to get 35 aka position 3.5.
If I understood correctly, you can use Array.reduce() to get the sum of the indexes where a match to some search term occurs. Then you can use the result from the reduce() to access your array of numbers:
let test = ["orange", "apple", "banana", "apple"];
let numbers = [10, 20, 30, 40, 50, 60, 70, 80, 90];
const getSumOfIdxs = (arr, str) =>
{
return arr.reduce((acc, curr, idx) =>
{
if (curr === str)
{
if (acc < 0) acc += 1;
acc += idx;
}
return acc;
}, -1);
}
let res = getSumOfIdxs(test, "apple");
console.log("Sum of indexes: ", res);
console.log("Element from numbers: ", numbers[res]);
res = getSumOfIdxs(test, "hello");
console.log("Sum of indexes: ", res);
console.log("Element from numbers: ", numbers[res]);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Yes, you can - filter through the array and find all your apples, then map out the indexes from the original array, reduce to one index, and get the item at that index.
const arr = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
const appleNums = [20, 30, 40];
const resultingAppleNum = arr[arr.filter(e => appleNums.includes(e)).map(e => arr.indexOf(e)).reduce((acc, curr) => acc + curr)];
console.log(resultingAppleNum);
I am unable to figure out how to write a function that will calculate all possible sums of of the elements of an array, with a max of 4 elements per addition.
Given
x = [1, 32, 921, 9213, 97, 23, 97, 81, 965, 82, 965, 823]
I need to go from (1+32) ~ (965+823) to (1+32+921+9213) ~ (965+82+965+823), calculating all the possible sums.
The output should be an array like this:
{33: [1, 32], 922: [1, 921], .... 2835: [965, 82, 965, 823]}
filled by all the possible sums.
It's not for homework, and what I was looking for is explained down there by Travis J: it was about permutations.
Thanks everybody, I hope this could be useful also to someone else.
jsFiddle Demo
You can use a permutation subset recursive algorithm to find the set of all of the sums and also their combinations.
var x = [1, 32, 921, 9213, 97, 23, 97, 81, 965, 82, 965, 823];
var sums = [];
var sets = [];
function SubSets(read, queued){
if( read.length == 4 || (read.length <= 4 && queued.length == 0) ){
if( read.length > 0 ){
var total = read.reduce(function(a,b){return a+b;},0);
if(sums.indexOf(total)==-1){
sums.push(total);
sets.push(read.slice().sort());
}
}
}else{
SubSets(read.concat(queued[0]),queued.slice(1));
SubSets(read,queued.slice(1));
}
}
SubSets([],x);
console.log(sums.sort(function(a,b){return a-b;}));
//log sums without sort to have them line up to sets or modify previous structure
console.log(sets);
There is a function to generate combinations of k members of a population of n here: https://gist.github.com/axelpale/3118596.
I won't reproduce the function here. You can combine it with another function to sum the combinations generated from an input array, e.g.
// Add combinations of k members of set
function getComboSums(set, k) {
return k_combinations(arr, n).map(function(a){
var sum=0;
a.forEach(function(v){sum += v})
return sum;
});
}
This can be combined with another function to get all combinations from 2 to 4 and concatenate them all together. Note that the total number of combinations in a set of 12 members is 781.
// Add all combinations from kStart to kEnd of set
function getComboSumRange(set, kStart, kEnd) {
var result = [];
for (var i=kStart; i <= kEnd; i++) {
result = result.concat(getComboSums(set, i));
}
return result;
}
Then given:
var arr = [1, 32, 921, 9213, 97, 23, 97, 81, 965, 82, 965, 823];
console.log(getComboSumRange(arr, 2, 4)) // length is 781
The length of 781 agrees with the calculated number of terms based on the formula for finding combinations of k in n:
n! / (k!(n - k)!)
and summing for k = 2 -> 4.
The result looks like:
[33, 922, 9214, 98, 24, 98 ... 2834, 1951, 2835];
You can see the terms start with:
arr[0] + arr[1], arr[0] + arr[2]], ...
and end with:
... arr[7] + arr[9] + arr[10] + arr[11], arr[8] + arr[9] + arr[10] + arr[11]