I want to write a function that passes an array and an optional number of values to be removed from the array as parameters. My function works when there is only 1 value, but fails when there is multiple values.
const removeFromArray = function (arr, ...theArgs) {
for (let i = 0; i < arr.length; i++) {
if (theArgs.includes(arr[i])) {
arr.splice(i, 1);
}
}
return arr;
};
You can use the filter method for that:
const removeFromArray = function (arr, ...theArgs) {
return arr.filter( val => !theArgs.includes(val) )
};
const list = [1,2,3];
const newList = removeFromArray(list, 2,3);
console.log(newList);
And a more terse version:
const removeFromArray = (arr, ...args)=> arr.filter( val => !args.includes(val) )
Tip: try to avoid mutating the original array and work on or return a copy during these operations.
The issue is with your indexing, you are finding the element using the index of arr, and deleting in the array, which is probably causing issue with indexing in loop.
Modify your code as follows
const removeFromArray = function (arr, ...theArgs) {
for (let i = 0; i < theArgs.length; i++) {
if (arr.includes(theArgs[i])) {
arr.splice(arr.indexOf(theArgs[i]), 1);
}
}
return arr;
};
The above fixes the code your way, but a better way of doing it would be using filter.
const removeFromArray = function (arr, ...theArgs) {
return arr.filter(ele => !theArgs.includes(ele))
}
I am writing it this way to purely maintain your function.
The problem is because you remove item from the array while being looping from that array.
Every time your for loop iterate the array, it will get a new array
e.g. (1,2,3,4,5 => 2,3,4,5), but the i value just keeping increasing by 1.
const removeFromArray = function (arr, ...theArgs) {
for (let i = 0; i < arr.length; i++) {
console.log(`arr:${arr}`,`item${arr[i]}`,`num${i}`)
console.log(arr[i])
if (theArgs.includes(arr[i])) {
arr.splice(i, 1);
}
}
return arr;
};
const testarray = [1,2,3,4,5]
console.log(removeFromArray(testarray,1,2,3))
I would suggest to use array as a second parameter.
var array1 = ['a','b','c'];
var elementsToRemove = ['a','b'];
const removeFromArray = function (array1, elementsToRemove) {
var filtered = array1.filter(function(value, index, array){
return elementsToRemove.includes(value);
});
return filtered;
}
console.log(removeFromArray(array1,elementsToRemove));
Related
I have a array of string.
let arr=["robin","rohit","roy"];
Need to find all the common character present in all the strings in array.
Output Eg: r,o
I have tried to create a function for above case with multiple loops but i want to know what should be the efficient way to achive it.
Here's a functional solution which will work with an array of any iterable value (not just strings), and uses object identity comparison for value equality:
function findCommon (iterA, iterB) {
const common = new Set();
const uniqueB = new Set(iterB);
for (const value of iterA) if (uniqueB.has(value)) common.add(value);
return common;
}
function findAllCommon (arrayOfIter) {
if (arrayOfIter.length === 0) return [];
let common = new Set(arrayOfIter[0]);
for (let i = 1; i < arrayOfIter.length; i += 1) {
common = findCommon(common, arrayOfIter[i]);
}
return [...common];
}
const arr = ['robin', 'rohit', 'roy'];
const result = findAllCommon(arr);
console.log(result);
const arr = ["roooooobin","rohit","roy"];
const commonChars = (arr) => {
const charsCount = arr.reduce((sum, word) => {
const wordChars = word.split('').reduce((ws, c) => {
ws[c] = 1;
return ws;
}, {});
Object.keys(wordChars).forEach((c) => {
sum[c] = (sum[c] || 0) + 1;
});
return sum;
}, {});
return Object.keys(charsCount).filter(key => charsCount[key] === arr.length);
}
console.log(commonChars(arr));
Okay, the idea is to count the amount of times each letter occurs but only counting 1 letter per string
let arr=["robin","rohit","roy"];
function commonLetter(array){
var count={} //object used for counting letters total
for(let i=0;i<array.length;i++){
//looping through the array
const cache={} //same letters only counted once here
for(let j=0;j<array[i].length;j++){
//looping through the string
let letter=array[i][j]
if(cache[letter]!==true){
//if letter not yet counted in this string
cache[letter]=true //well now it is counted in this string
count[letter]=(count[letter]||0)+1
//I don't say count[letter]++ because count[letter] may not be defined yet, hence (count[letter]||0)
}
}
}
return Object.keys(count)
.filter(letter=>count[letter]===array.length)
.join(',')
}
//usage
console.log(commonLetter(arr))
No matter which way you choose, you will still need to count all characters, you cannot get around O(n*2) as far as I know.
arr=["robin","rohit","roy"];
let commonChars = sumCommonCharacters(arr);
function sumCommonCharacters(arr) {
data = {};
for(let i = 0; i < arr.length; i++) {
for(let char in arr[i]) {
let key = arr[i][char];
data[key] = (data[key] != null) ? data[key]+1 : 1;
}
}
return data;
}
console.log(commonChars);
Here is a 1 liner if anyone interested
new Set(arr.map(d => [...d]).flat(Infinity).reduce((ac,d) => {(new RegExp(`(?:.*${d}.*){${arr.length}}`)).test(arr) && ac.push(d); return ac},[])) //{r,o}
You can use an object to check for the occurrences of each character. loop on the words in the array, then loop on the chars of each word.
let arr = ["robin","rohit","roy"];
const restWords = arr.slice(1);
const result = arr[0].split('').filter(char =>
restWords.every(word => word.includes(char)))
const uniqueChars = Array.from(new Set(result));
console.log(uniqueChars);
I am writing a very easy function where I am checking the even numbers from an array of integer and adding those even numbers into the new array.
But after getting the even numbers from first array when I am trying to push into second array its showing undefined.
const arr = [1,2,3,4,5,6];
const newArr = [];
const loop = () => {
for (var item of array) {
if (item % 2 == 0) {
console.log(item);
newArr.push(item);
}
}
};
console.log(loop());
Output
2
4
6
undefined
Why new array is showing undefined.
You can do it simply with forEach.
const arr = [1,2,3,4,5,6];
const newArr = [];
arr.forEach(item => {
if (item % 2 == 0) {
newArr.push(item);
}
})
console.log(newArr);
either return the newArray or execute the loop method and print the new Array.
The reason why you get undefined is because loop is currently a void operator and returning nothing. so if you want the loop method to return the array then the second code sample I showed is the better solution. if you just want to print the array then the first one does the trick.
const arr = [1,2,3,4,5,6];
const newArr = [];
arr.forEach(item => {
if (item % 2 == 0) {
newArr.push(item);
}
})
console.log(newArr);
or
const arr = [1,2,3,4,5,6];
const loop = () => {
const newArr = [];
for (var item of arr) {
if (item % 2 == 0) {
console.log(item);
newArr.push(item);
}
}
return newArr
};
console.log(loop());
both will work.
let array=[1,1,2,3,4,4,5,5,6,6,7,8]:
I want to get 2 array of unique and duplicate elements: duplicate element's array1:[1,4,5,6] unique element's array2:[2,3,7,8]
Help is very much appreciated.
Simply use a map to filter out duplicates. Here's a working solution.
let arr= [1,1,2,3,4,4,5,5,6,6,7,8];
function uniqueAndDuplicates() {
var obj = {};
var duplicates = [];
var noDup = [];
for(var i = 0; i < arr.length; i++){
if(!obj[arr[i]]){
obj[arr[i]] = 1;
noDup.push(arr[i]);
} else {
duplicates.push(arr[i]);
}
}
var unique = noDup.filter(function(item, index){
if(!duplicates.includes(noDup[index])){
return noDup[index];
}
});
return {
unique,
duplicates
}
}
console.log(uniqueAndDuplicates(arr));
One solution is you can create a freq map and then you can essentially create an Array from that map then filter out the counts greater than 1 and less than 1.
let array=[1,1,2,3,4,4,5,5,6,6,7,8]
const returnUniqueAndDuplicateElements = (arr) => {
let freqMap = {};
for(const idx in arr){
let number = arr[idx];
if(!freqMap[number]){
freqMap[number]=0;
}
freqMap[number]++;
}
const entries = Object.entries(freqMap);
return {
unique: entries.filter(([, freq]) => freq <= 1).map(item => Number(item[0])),
duplicates: entries.filter(([, freq]) => freq > 1).map(item => Number(item[0]))
}
}
console.log(returnUniqueAndDuplicateElements(array))
I am adding my solution since there is none with JS sets[?] just yet:
function uniqueAndDuplicate(arrayOfNumbers) {
const unique = new Set();
const duplicate = new Set();
arrayOfNumbers.forEach((elem) => {
if (unique.has(elem)) {
unique.delete(elem);
duplicate.add(elem);
} else if (!duplicate.has(elem)) {
unique.add(elem);
}
});
return {
unique: [...unique],
duplicate: [...duplicate],
};
}
console.log(uniqueAndDuplicate([1,1,2,3,4,4,5,5,6,6,7,8]));
I've only been studying javascript for three weeks now and need help on a task.
I want to implement a function, called test, which takes a list and a function as arguments. The test function should call the function that was submitted as an argument once for each value in the list, with the list value in question as an argument, and will return a NEW list containing only the list values for which the argument function returned true. And I want to do that WITHOUT using the filter() method.
How can I think here? Is my code below a good start? I appreciate all the help I can get here so I can understand this.
let x = ["1", "2", "3"];
function test(x, s) {
for (let i = 0; i < x.length; i++) {
}
return
}
The code you provided is a good start, it provides a way of looping through all the elements in the list, which is a good starting point. I do suggest however that you change the names of your arguments so that they better represent the data they hold.
Your next step is to call the function passed in as an argument (f) for each element in your list and check whether or not it returns true. If it does, then you can add this element to a new list (which holds the list of values to return).
Once your loop is complete, you can return this new list. Take a look at an example below to get an understand of how you might implement this:
let x = [1, 2, 3, 4];
function test(lst, f) {
let new_list = [];
for (let i = 0; i < lst.length; i++) {
if(f(lst[i])) { // check if the function gives back a "truthy" value
new_list.push(lst[i]);
}
}
return new_list;
}
let result = test(x, function(list_element) {
return list_element % 2 === 0; // return true if element is even
});
console.log(result);
You could also achieve this in a number of different ways, such as using .reduce() and a ternary to make the method nice and concise:
const x = [1, 2, 3, 4];
const test = (lst, f) =>
lst.reduce((acc, elem) => f(elem) ? [...acc, elem] : acc, []);
const res = test(x, n => n % 2 === 0);
console.log(res);
You can create an empty array at the start of your function, that you populate while reading your array before returning it.
As you don't want to use filter, I will provide a solution using forEach, and an other using a basic for loop.
let x = ["1", "2", "3"];
function testFor(list, testFct) {
const resultArray = [];
for (let i = 0; i < list.length; i++) {
if (testFct(list[i])) {
resultArray.push(list[i]);
}
}
return resultArray;
}
function testForeach(list, testFct) {
const resultArray = [];
list.forEach((element) => {
if (testFct(element)) {
resultArray.push(element);
}
})
return resultArray;
}
console.log(testFor(x, (el) => el % 2));
console.log(testForeach(x, (el) => el % 2));
But at the end of the day, I don't see why you could not use filter, as it returns a new array anyway.
If you want to do that in a simple way is this -->
let x = ["1", "2", "3"];
function myFunction(element){
if (element == "1" || element == "2"){
return true
}
return false
}
function test(list, myFunction) {
let newList = [];
for (let i = 0; i < list.length; i++) {
let element = list[i];
if (myFunction(element)){
newList.push(element);
}
}
return newList
}
test(x, myFunction)
There is another simpler way using filter -->
let x = ["1", "2", "3"];
function myFunction(element){
if (element == "1" || element == "2"){
return true
}
return false
}
function test(list, myFunction) {
return list.filter(myFunction)
}
test(x, myFunction)
The problem is to find the unique number in a array such as [2,2,2,5].
The output should be 5 as it is the 1 unique element in the array.
I have attempted this:
function findUniq(arr) {
var b= arr[0];
var c;
for(var i=0; i<arr.length; i++)
{
if(arr[i]===b )
{
b=arr[i]
}
else
{
c=arr[i];
}
}
return c
console.log(findUniq([3, 5, 3, 3, 3]))
This works fine unless the unique number is the first element in the array. How do I fix this?
You can use indexOf and lastIndexOf to see if a value occurs more than once in the array (if it does, they will be different), and if so, it is not the unique value. Use filter to process the array:
let array = [2,2,2,5];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [5,3,3,3,3];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [4,4,5,4];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
You can create a recursive function that will take the first element of the array and see if it exists in the rest of it, if it does, it will take the next element and do the same, return the element if it doesn't exist in the rest of the array :
const arr = [3, 3, 3, 5, 3];
const find = arr => {
const [f, ...rest] = arr;
if(rest.includes(f))
return find(rest);
else
return f;
}
const result = find(arr);
console.log(result);
Note that this will return the last element if all of them are the same [3,3,3] will return 3
Try something like this using a set, which only stores unique elements:
var set = new Set(arr);
// count instances of each element in set
result = {};
for(var i = 0; i < a.length; ++i) {
if(!result[arr[i]])
result[arr[i]] = 0;
++result[arr[i]];
}
for (var value in result) {
if (value == 1) {
return value;
}
}
// if there isn't any
return false;
This should work, please tell me if it doesn't.
This is another implementation that is surely less efficient than that of #Nick's, but it is a valid algorithm anyway:
function findUniq(arr) {
var elemCount = new Map();
var uniq = [];
// Initialize elements conts
for (var k of arr.values()) {
elemCount.set(k, 0);
}
// Count elements
for (var k of arr.values()) {
elemCount.set(k, elemCount.get(k) + 1);
}
// Add uniq elements to array
for (var [k, v] of elemCount.entries()) {
if (v === 1) uniq.push(k);
}
return uniq;
}
console.log(findUniq([3, 5, 3, 3, 3]))
if you prefer .reduce over .map for your use case (for performance/etc. reasons):
function existance(data) {
return data.reduce((a, c) => (data.indexOf(c) === data.lastIndexOf(c)) ? a.concat(c) : a, []);
}
console.log(existance([1,1,1,2]));
console.log(existance([1,1,2,3,4,5,5,6,6,6]));