One of the challanging question I got in office, which i could not able to come out of it. need the help here.
const array = [2, 7, 11, 15], target = 9;
in the above i have an array and target as 9, as well this target can change any of value as 18,26 like so. the result should show the indexOf array which used for get the target. for example at present it is 9, so the result should be [0,1] (2+7). if the target is 26 then result should be [2,3]. how to achieve this?
for my try the first attempt is working. but rest of them not. need the help.
my code :
const array = [2, 7, 11, 15], target = 9;
const result = [];
const outPut = array.reduce((c,v,i,a) => {
if(c !== target && c < target) {
result.push(a.indexOf(v));
}
return c + v;
}, 0);
console(result);
Here's the brute force solution:
Get all the subsets of the array.
Compute the sum of each subset.
Filter the subsets to those whose sum is the target.
const array = [1, 2, 7, 8, 9, -2];
const target = 9;
const getAllSubsets = array => array.reduce(
(subsets, value) => subsets.concat(subsets.map(set => [...set, value])),
[[]]
);
const subsets = getAllSubsets(array);
const result = subsets.filter(
subset => subset.reduce((partialSum, element) => partialSum + element, 0) == target
);
console.log(result);
This example produces all the subsets of [1, 2, 7, 8, 9, -2] that sum to 9.
Output:
[ [ 2, 7 ], [ 1, 8 ], [ 9 ], [ 1, 2, 8, -2 ], [ 2, 9, -2 ] ]
You only need to make two small changes to make this work with indices instead of the actual values:
get all subsets of array.map((_, i) => i) instead of array to get the indices
sum using array[element] instead of element.
const array = [1, 2, 7, 8, 9, -2];
const target = 9;
const getAllSubsets = array => array.reduce(
(subsets, value) => subsets.concat(subsets.map(set => [...set, value])),
[[]]
);
const subsets = getAllSubsets(array.map((_, i) => i));
const result = subsets.filter(
subset => subset.reduce((partialSum, element) => partialSum + array[element], 0) == target
);
console.log(result);
The problem with this approach is that you might end up adding the wrong elements; for example, if target was 13, your code would first add 2 and 7 and then not return the correct result because it wouldn't then consider adding 11 since that exceeds the target. Instead, you should use a two-pointer technique (see https://www.geeksforgeeks.org/two-pointers-technique/)
const array = [2, 7, 11, 15];
let result = [];
const getResult = (target) => {
for(let i =0; i < array.length;i++){
let requiredValue = target - array[i];
if(array.indexOf(requiredValue) > -1) {
result = [array.indexOf(array[i]), array.indexOf(requiredValue)].sort();
}
if(array.indexOf(requiredValue) < -1) {
result = [0];
}
}
}
getResult(9)
console.log(result);
getResult(18)
console.log(result);
getResult(26)
console.log(result);
Here is my solution:
const array = [2, 7, 11, 15];
const target = 26;
let result = [];
for(let i =0; i < array.length;i++){
let requiredValue = target - array[i];
if(array.indexOf(requiredValue) > -1) {
result = [array.indexOf(array[i]), array.indexOf(requiredValue)].sort();
}
}
console.log(result);
it works for me. any one find the issue, pls comment. Change the target and play.
Related
const source = [2, 9, 9, 1, 6];
const ans = source.filter((item, index, arr)=> arr.indexOf(item) === index);
console.log(ans);
here i'm able to remove the duplicate elements but how to make 9 which is repeated highest to come first in the new array??
any help would be appreciated
ans should be [9, 2, 1, 6]
This should work for all cases where array should be sorted by most number of reoccurrences.
const source = [2,1,9,9,6];
const indexes = [];
var ans = source.filter((item,index,arr)=>{
if(arr.indexOf(item) === index){
indexes.push({item:item,count:1})
return true;
}
else if(arr.indexOf(item) !== index){
indexes[indexes.findIndex(object=> object.item === item)].count++
return false;
}
return false;
})
ans =(indexes.sort((a,b)=>{return b.count - a.count}).map(obj =>obj.item))
console.log(ans)
If using more space is okay, you can use a hash map for counting elements and then convert it to an array.
Something like this.
let arr = [2, 9, 9, 1, 6];
// count elements
const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());
// sort by values and convert back to array
const res = [...map.entries()].sort((a, b) => b[0] - a[0]).map((a) => {
return a[0]
});
console.log(res)
Try This
function removeAndSort(arr) {
var order = {};
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
if (value in order) {
order[value]++;
} else {
order[value] = 1;
}
}
var result = [];
for (value in order) {
result.push(value);
}
function sort(a, b) {
return order[b] - order[a];
}
return result.sort(sort);
}
console.log(removeAndSort([2, 9, 9, 1, 6]));
It's Absolutely Working, Check It
Instead of removing the duplicates with the code you have you need to find a way to create a frequency map to save the duplicates information. In this example I create a map using an object like this...
const freq = { 9: [9, 2], 1: [1, 1] ... };
which uses the current iterated element as a key in an object, and the value is the element along with its duplicate value. You can grab those arrays using Object.values, sort them by that duplicate value, and then map over that sorted nested array to produce the result.
Note, however, due to the sorting process this results in [9, 1, 2, 6].
const source = [2, 9, 9, 1, 6];
// `reduce` over the array creating a key/value pair where
// the value is an array - the first element is the element value,
// and the second value is its duplicate value
const nested = source.reduce((acc, c) => {
// If the object property as defined by the element
// value doesn't exist assign an array to it initialising
// the duplicate value to zero
acc[c] ??= [c, 0];
// Increment the duplicate value
++acc[c][1];
// Return the object for the next iteration
return acc;
}, {});
// We take the `Object.values` of the object (a series of
// nested arrays and sort them by their duplicate value,
// finally `mapping` over the sorted arrays and extracting
// the first element of each
const out = Object.values(nested).sort((a, b) => {
return b[1] - a[1];
}).map(arr => arr[0]);
console.log(out);
Additional documentation
Logical nullish assignment
function sortAndFilter(source) {
let duplicates = {};
//count the duplications
source.filter((item, index, arr) => {
if(arr.indexOf(item) != index)
return duplicates[item] = (duplicates[item] || 0) + 1;
duplicates[item] = 0;
})
//sort the numbers based on the amount of duplications
return Object.keys(duplicates).map(a => parseInt(a)).sort((a, b) => duplicates[b] - duplicates[a]);
}
Output: [ 9, 6, 2, 1 ]
This could do the job
this is best answer for your question
const source = [2, 9, 9, 1, 6];
function duplicate(array) {
let duplicates = array.filter((item, index) => array.indexOf(item) !== index);
return duplicates.concat(array.filter((item) => !duplicates.includes(item)));
}
console.log(duplicate(source));
function myFunction() {
const source = [2, 9, 9, 1, 6];
const ans = source.filter((item, index, arr)=> arr.indexOf(item) === index);
ans.sort((a, b) => b-a);
console.log(ans);
}
Output: [ 9, 6, 2, 1 ]
I've tried a few approaches to this but I can't seem to come up with a viable solution...
In short, I want to create a function to transform a 1D array of any length into a new 2D array of a specific length. Each value from the 1D array should be sequentially placed into each child-array up to the specified length, then start back at the first child-array.
Input / Desired Output Below:
function groupArray(arr, numberOfGroups) {
...
};
// Input Data
const items = [1, 2, 3, 4, 5, 6, 7];
const size = 3;
console.log(groupArray(items, size));
// Expected Output
// [[1, 4, 7], [2, 5], [3, 6]]
You could take the reminder operator % with index and wanted size of the array for getting the right target array.
const
groupArray = (array, size) => array.reduce((result, value, index) => {
const target = index % size;
if (!result[target]) result[target] = [];
result[target].push(value);
return result;
}, []);
console.log(groupArray([1, 2, 3, 4, 5, 6, 7], 3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using nested for
function groupArray(arr, numberOfGroups) {
var result = []
for (var i = 0; i < numberOfGroups; i++) {
var subarr = []
for (var j = i; j < arr.length; j += numberOfGroups) {
subarr.push(arr[j])
}
result.push(subarr)
}
return result
};
// Input Data
const items = [1, 2, 3, 4, 5, 6, 7];
const size = 3;
console.log(groupArray(items, size));
Also something like this would do it,
you'd not need to mutate any input
const chunkify = (step, list) => list.reduce(
([chunk, rest], item, i) => {
const pick = i % step === 0;
return [
chunk.concat(pick ? item : []),
rest.concat(pick ? [] : item),
];
},
[[], []],
);
const group = (step, list, result = []) => {
if (!list.length) { return result; }
const [chunk, rest] = chunkify(step, list);
return group(step - 1, rest, [...result, chunk]);
};
const data = [1, 2, 3, 4, 5, 6, 7];
const step = 3;
console.log(
group(step, data),
);
Have method next, each call will return next index and when limit reaches numberOfGroups reset the index 0. (in this case, it will be like 0, 1, 2, 0, 1, 2....)
With this method, can easily push to corresponding output sub array.
const groupArray = (arr, numberOfGroups) => {
const output = Array.from({ length: numberOfGroups }, () => []);
const next = index => index % numberOfGroups;
arr.forEach((num, i) => output[next(i)].push(num));
return output;
};
// Input Data
const items = [1, 2, 3, 4, 5, 6, 7];
const size = 3;
console.log(groupArray(items, size));
I have an array of values. I want to make a second array based on the first one with stricter criteria. For example, what I want specifically is:
arrayOne[1,1,1,1,1,2,2,2,3,3,3,3,4,4,4,4,4,5,5,5]
How would I make it so in my new array, only the values that show up 5 times are a part of the array and only show up once. Example: arrayTwo [1,4]
I'm fairly new to JavaScript and have been given an opportunity to code a decision making system for one of my business courses instead of doing the final exam. Any help you can give would be much appreciated. Thank You.
You could use a hash table, which counts each found element and then use the count for filtering and get only the fifth element as result set in a single loop.
var array = [1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5],
count = Object.create(null),
result = array.filter(v => (count[v] = (count[v] || 0) + 1) === 5);
console.log(result);
I commented the code with the steps I took:
const arrayOne = [1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5];
function method(arr, minimum) {
//Create an object containing the amount each number occurs
const occurrences = arr.reduce((o, n) => {
//If number is already in the object add 1
if (o[n]) o[n] = o[n] + 1;
//Else set its occurence to 1
else o[n] = 1;
//Return the object for the next iteration
return o;
}, {});
//Deduplicate the array be creating a Set(every elements can only occur once) and spread it back into an array
const deduplicate = [...new Set(arr)];
//Filter array to only contain elements which have the minimum of occurences
const filtered = deduplicate.filter(n => occurrences[n] >= minimum);
return filtered;
}
console.log(method(arrayOne, 5));
You can use a Map for this.
let arrayOne = [1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5];
let counterMap = new Map();
arrayOne.forEach(value => {
let valueStr = value.toString();
counterMap.set(valueStr, counterMap.has(valueStr) ? counterMap.get(valueStr) + 1 : 1);
});
let arrayTwo = [];
counterMap.forEach((value, key, map) => {
if(value >= 5) {
arrayTwo.push(key);
}
});
console.log(arrayTwo);
Not the most elegant answer, but I assume you're looking just to find all values that appear at least 5 times.
const arrayOne = [1,1,1,1,1,2,2,2,3,3,3,3,4,4,4,4,4,5,5,5]
const arrayTwo = Object.entries(arrayOne.reduce((obj, num) => {
if(!obj[num]){
obj[num] = 1
} else {
obj[num] = obj[num] + 1
}
return obj
}, {})).filter(([key, value]) => {
return value >= 5
}).map((item) => {
return parseInt(item[0])
})
console.log(arrayTwo)
const a = [1,1,1,1,1,2,2,2,3,3,3,3,4,4,4,4,4,5,5,5,5,5,5,5,5,5];
Define a function that will take an array and numOfOccurrences
const filterByOcur = (arr, numOfOccurrences) => {
// create an object to act as a counter this will let us
// iterate over the array only once
const counter = {};
const res = new Set();
for (let num of arr) {
// if it's the first time we see the num set counter.num to 1;
if (!counter[num]) counter[num] = 1;
// if counter.num is greater or equal to numOfOccurrences
// and we don't have the num in the set add it to the set
else if (++counter[num] >= numOfOccurrences && !res.has(num)) res.add(num);
}
// spread the Set into an array
return [...res];
};
console.log(
filterByOcur(a, 5)
);
There is number of ways of doing this, I will try to explain this step by step:
Array declaration
const a = [1,1,1,1,1,2,2,2,3,3,3,3,4,4,4,4,4,5,5,5]
Method to count elements in an array, we are using reducer function that as a first argument takes object where key is our value from array and has a incremental number as a value. Remeber to start reducer with empty object
const counted = a.reduce((counter, value) => {
if (counter[value]) counter[value]++
else counter[value] = 1
return counter
}, {})
Make your array unique with Set constructor
const uniq = Array.from(new Set(a))
Fire filter functions on the uniq array with a help of counted array, look how we access it:
const onlyOne = uniq.filter(val => counted[val] === 1)
const onlyFive = uniq.filter(val => counted[val] === 5)
Merge all filtered arrays into one
const final = [].concat(onlyOne, onlyFive)
This question already has answers here:
Remove entry from array using another array
(7 answers)
Closed 3 years ago.
I am trying to figure out which way is the best, in terms of performance.
Given the following problem;
You have one array of numbers and another one with numbers you want to remove from the first array.
I have tried a couple of things: https://codepen.io/bluebrown/pen/VRGgpm
let dataArray = [2,4,5,8,1,9,3];
let blackList = [3,5,8,7];
function findFaulty(data, bad) {
if (bad.length > 0) {
let cleanData = [];
data.forEach(item => {
let x = 0;
bad.forEach(b => {
if (b === item) return;
x++;
if (x >= bad.length) cleanData.push(item);
});
});
return cleanData;
}
return data;
};
console.log(findFaulty(dataArray, blackList));
Then: https://codepen.io/bluebrown/pen/GeXwBL?editors=0012
let dataArray = [2, 4, 5, 8, 1, 9, 3];
let blackList = [2, 3];
function filterData(data, bad) {
bad.forEach((b, i, a) => a[i] = data.indexOf(b));
bad.filter(x => x > -1).forEach((b, i) => data.splice(b, 1, -1));
return data.filter(d => d > -1)
};
console.log(filterData(dataArray, blackList));
and finally: https://codepen.io/bluebrown/pen/EMdyVg
let data = [2, 4, 5, 8, 1, 9, 3];
let faulty = [2, 1, 5, 6];
let clean = data.filter(d => faulty.indexOf(d) < 0 );
console.log(clean);
You could iterate the array from the end and splice found items.
function filter(items, remove) {
var i = items.length;
while (i--) {
if (remove.includes(items[i])) items.splice(i, 1);
}
return items;
}
console.log(...filter([2, 4, 5, 8, 1, 9, 3], [3, 5, 8, 7]));
With your existing data formats you can use filter and includes.
let dataArray = [2,4,5,8,1,9,3];
let blackList = [3,5,8,7];
let op = dataArray.filter(e=> !blackList.includes(e))
console.log(op)
But IMO most performant way will be using blackList as object,
let dataArray = [2,4,5,8,1,9,3];
let blackList = {3:false,5:false,8:false,7:false};
let op = dataArray.filter(e=> blackList[e] !== false)
console.log(op)
So if I want to remove nesting from array items I can definitely do it:
var nestedArrs = [[1],[2],[3],[4],[5]];
var denestedArr = [].concat.apply([], nestedArrs);
console.log(denestedArr) //prints [1, 2, 3, 4, 5];
but what about if I need to go backwards and add nesting?
var unnestedArr = [7, 8, 9, 10];
var nestedArr = [] ? // Say I want to add nesting to every other item in arr
console.log(nestedArr); //so I wanted it to print [[7], 8, [9], 10]
//& nested Arr needs to be based upon the starting unnestedArr.
var unnestedArr = [7, 8, 9, 10];
var nestedArr = unnestedArr.map(function(item, index) {
return index % 2 === 0 ? [ item ] : item;
});
console.log(nestedArr);
Similar to Andreas's answer, I would suggest a function programming approach using .map.
If you don't like "hard-coding" the "every other" decision criterion , you could make a "mask".
const unnestedArr = [7, 8, 9, 10];
// Here we define which items should be nested
const isEven = x => x % 2 === 0;
const nestCriterion = (item, index) => isEven(index);
const shouldBeNested = unnestedArr.map(nestCriterion); // = [true, false, true, false];
// Next we perform the nesting to the items we identified above
const nestedArr = unnestedArr.map((item, index) => {
return shouldBeNested[index] ? [ item ] : item;
});
// Alternatively, we could've just used "one big function" like this:
const nestedArr2 = unnestedArr.map((item, index) => {
if (index % 2 === 0) {
return [ item ];
}
else {
return item;
}
});
// If we wanted to modify the array in place (instead of creating a new one)
// we could've used .forEach instead of .map and modified (mutated)
// elements of interest (e.g. by wrapping them in an array)
console.log(unnestedArr, nestedArr, nestedArr2);
Here's an implementation on jsbin.com