I want to check if an array contains "role". If it does, I want to move the "role" to the front of the array.
var data= ["email","role","type","name"];
if ("role" in data) data.remove(data.indexOf("role")); data.unshift("role")
data;
Here, I got the result:
["role", "email", "role", "type", "name"]
How can I fix this?
You can sort the array and specify that the value "role" comes before all other values, and that all other values are equal:
var first = "role";
data.sort(function(x,y){ return x == first ? -1 : y == first ? 1 : 0; });
Demo: http://jsfiddle.net/Guffa/7ST24/
The cleanest solution in ES6 in my opinion:
let data = ["email","role","type","name"];
data = data.filter(item => item !== "role");
data.unshift("role");
let data = [0, 1, 2, 3, 4, 5];
let index = 3;
data.unshift(data.splice(index, 1)[0]);
// data = [3, 0, 1, 2, 4, 5]
My first thought would be:
var data= ["email","role","type","name"];
// if it's not there, or is already the first element (of index 0)
// then there's no point going further:
if (data.indexOf('role') > 0) {
// find the current index of 'role':
var index = data.indexOf('role');
// using splice to remove elements from the array, starting at
// the identified index, and affecting 1 element(s):
data.splice(index,1);
// putting the 'role' string back in the array:
data.unshift('role');
}
console.log(data);
To revise, and tidy up a little:
if (data.indexOf('role') > 0) {
data.splice(data.indexOf('role'), 1);
data.unshift('role');
}
References:
Array.indexOf().
Array.prototype.splice().
Array.unshift().
Here is an immutable solution if needed :
const newData = [
data.find(item => item === 'role'),
...data.filter(item => item !== 'role'),
],
If you don't want to alter the existing array, you can use ES6 destructuring with the filter method to create a new copy while maintaining the order of the other items.
const data = ["email", "role", "type", "name"];
const newData = ['role', ...data.filter(item => item !== 'role')];
If you have an array of objects you could shift the start-index with splice and push. Splice replaces the original array with the part of the array starting from the desired index and returns the part it removes (the stuff before the index) which you push.
let friends = [{
id: 1,
name: "Sam",
},
{
id: 2,
name: "Steven",
},
{
id: 3,
name: "Tom",
},
{
id: 4,
name: "Nora",
},
{
id: 5,
name: "Jessy",
}
];
const tomsIndex = friends.findIndex(friend => friend.name == 'Tom');
friends.push(...friends.splice(0, tomsIndex));
console.log(friends);
To check whether an item exists in an array you should to use .includes() instead of in (as already noted here, in is for properties in objects).
This function does what you are looking for:
(removes the item from the position it is in and reads
in front)
data = ["email","role","type","name"];
moveToFirst("role", data);
function moveToFirst( stringToMove, arrayIn ){
if ( arrayIn.includes(stringToMove) ){
let currentIndex = arrayIn.indexOf(stringToMove);
arrayIn.splice(currentIndex, 1);
arrayIn.unshift(stringToMove);
}
}
console.log(data);
Similar to #Tandroid's answer but a more general solution:
const putItemsFirst = ({ findFunction, array }) => [
...array.filter(findFunction),
...array.filter(item => !findFunction(item)),
];
Can be used like this
putItemsFirst({
array: ["email","role","type","name"],
findFunction: item => item === 'role',
})
Something similar to this is what I ended up using,
I would go with this ES6 solution. It doesn't mutate the original array(considering it's not nested), doesn't traverse through the array(filter) and you're not just limited to 0th index for shifting the array item.
const moveArrayItem = (array, fromIndex, toIndex) => {
const arr = [...array];
arr.splice(toIndex, 0, ...arr.splice(fromIndex, 1));
return arr;
}
const arr = ["a", "b", "c", "d", "e", "f", "g"];
console.log(moveArrayItem(arr, 4, 0))
// [ 'e', 'a', 'b', 'c', 'd', 'f', 'g' ]
The most readable way in my opinion.
array.sort((a, b) => (a === value && -1) || (b === value && 1) || 0)
var data= ["email","role","type","name"];
data.splice(data.indexOf("role"), 1);
data.unshift('role');
You could take the delta of the check with the wanted value at top.
var data = ["email", "role", "type", "name"];
data.sort((a, b) => (b === 'role') - (a === 'role'));
console.log(data);
A reusable ES6/Typescript solution:
const moveToStart = <T>(array: T[], predicate: (item: T) => boolean): T[] => {
return array.sort((a, b) => {
if (predicate(a)) return -1;
if (predicate(b)) return 1;
return 0;
});
};
const data = ["email", "role", "type", "name"];
const result = moveToStart(data, (item) => item === "role"))
the in operator is about properties, not about items in arrays. See How do I check if an array includes an object in JavaScript? for what to use else.
You're missing braces around the two (!) statements in your if-block
I'm not sure whether that .remove() function you're using does take an index of an item.
Using lodash _.sortBy. If the item is role, it will be sorted first, otherwise second. This works fine too if there is no role
var data = ["email", "role", "type", "name"];
var sorted = _.sortBy(data, function(item) {
return item === 'role' ? 0 : 1;
});
console.log(sorted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Just wanted to drop this on here since according to other comments Guffa's answer seems to be gaining traction, the final tertiary - which was one of the negative comments on that answer is unnecessary. Also using arrow functions makes it seem much cleaner.
Also, it is easily expandable to handling Arrays of objects.
const first = "role";
data.sort((x, y) => first === x ? -1 : first === y)
I believe this should also handle the worry of the rest of the array being affected. When the sort function returns a number less than 0 (first === x), the element will move toward the start of the Array, when it returns 0 (first !== y), there will be no movement, and when a number greater than 0 (first === y), x will move toward the end of the Array, all in relation to x and y. Therefore, when neither x or y are equivalent to the desired first element (or it's identifier in the case of sorting objects), there will be no movement of the two in relation to each other.
For an object:
const unsorted = [{'id': 'test'}, {'id': 'something'}, {'id': 'else'}];
const first = 'something';
const sorted = unsorted.sort((x,y) => x['id'] === first ? -1 : y['id'] === first);
My solution is a bit different as it mutates original array instead of creating a new one.
It will move given item to start of the array and move item that was previously at start in the place of requested item.
function moveElementToStart<T>(items: T[], item: T) {
const itemIndex = items.indexOf(item);
// Item is not found or it is already on start
if (itemIndex === -1 || itemIndex === 0) return;
// Get item that is currently at start
const currentItemAtStart = items[0];
// Swap this item position with item we want to put on start
items[0] = item;
items[itemIndex] = currentItemAtStart;
}
Generalized one-liners:
const data = ["a", "b", "c", "d", "e", "f"];
const [from, take] = [3, 2];
data.unshift(...data.splice(from, take));
// alternatively
data = [...data.splice(from, take), ...data];
// ["d", "e", "a", "b", "c", "f"]
const moveToFront = (arr, queryStr) =>
arr.reduce((acc, curr) => {
if (queryStr === curr) {
return [curr, ...acc];
}
return [...acc, curr];
}, []);
const data = ['email', 'role', 'type', 'name'];
console.log(moveToFront(data, 'role'))
const moveTargetToBeginningOfArray = (arr, target) => {
// loop through array
for (let i = 0; i < arr.length; i++){
// if current indexed element is the target
if(arr[i] === target){
// remove that target element
arr.splice(i, 1)
// then add a target element to the beginning of the array
arr.unshift(target)
}
}
return arr;
};
// quick sanity check, before and after both are correct
const arrayOfStrings = ["email", "role", "type", "name", "role", "role"];
console.log('before:', arrayOfStrings)
console.log('after:', moveTargetToBeginningOfArray(arrayOfStrings, "role"))
// this would also work for numbers
var arrayOfNumbers = [2,4,0,3,0,1,0]
console.log('before:', arrayOfNumbers)
console.log('after:', moveTargetToBeginningOfArray(arrayOfNumbers, 0))
function unshiftFrom(arr, index) {
if (index > -1 && index < arr.length) { // validate index
var [itemToMove] = arr.splice(index, 1)
arr.unshift(itemToMove)
}
return arr // optional
}
//we can do this from scratch
let tempList=["person1","person2","person3"];
let result=[];
//suppose i need to move "person2" to first place
let movableValue=null;
let query="person2"; //here you could use any type of query based on your problem
tempList.map((e)=>{
if(e!==query){
result.push(e);
}else if(e===query){
movableValue=e;
}
})
if(movableValue!==null){
result.unshift(movableValue);
}
console.log(result)
)
var i = -1;
while (i < data.length) {
if (data[i] === "role") {
data.splice(i, 1);
break;
}
i++;
}
data.unshift("role");
indexOf only has limited browser support, not being recognized by IE7-8. So I wouldn't use it if I were you, even at the expense of a few lines' worth of code conciseness. You also want to put a semicolon at the end of the "unshift" statement. splice()'s first argument specifies the index to start removing elements, and the second argument specifies the number of arguments to remove.
data.unshift(data.splice(data.indexOf('role'), 1)[0])
data.indexOf('role') will find the index of 'role' in the array and then the original array is spliced to remove the 'role' element, which is added to the beginning of the array using unshift
var data= ["email","role","type","name"];
if ("role" in data) data.splice(data.indexOf("role"),1); data.unshift("role");
data;
Related
I have a target array ["apple","banana","orange"], and I want to check if other arrays contain any one of the target array elements.
For example:
["apple","grape"] //returns true;
["apple","banana","pineapple"] //returns true;
["grape", "pineapple"] //returns false;
How can I do it in JavaScript?
Vanilla JS
ES2016:
const found = arr1.some(r=> arr2.includes(r))
ES6:
const found = arr1.some(r=> arr2.indexOf(r) >= 0)
How it works
some(..) checks each element of the array against a test function and returns true if any element of the array passes the test function, otherwise, it returns false. indexOf(..) >= 0 and includes(..) both return true if the given argument is present in the array.
vanilla js
/**
* #description determine if an array contains one or more items from another array.
* #param {array} haystack the array to search.
* #param {array} arr the array providing items to check for in the haystack.
* #return {boolean} true|false if haystack contains at least one item from arr.
*/
var findOne = function (haystack, arr) {
return arr.some(function (v) {
return haystack.indexOf(v) >= 0;
});
};
As noted by #loganfsmyth you can shorten it in ES2016 to
/**
* #description determine if an array contains one or more items from another array.
* #param {array} haystack the array to search.
* #param {array} arr the array providing items to check for in the haystack.
* #return {boolean} true|false if haystack contains at least one item from arr.
*/
const findOne = (haystack, arr) => {
return arr.some(v => haystack.includes(v));
};
or simply as arr.some(v => haystack.includes(v));
If you want to determine if the array has all the items from the other array, replace some() to every()
or as arr.every(v => haystack.includes(v));
ES6 solution:
let arr1 = [1, 2, 3];
let arr2 = [2, 3];
let isFounded = arr1.some( ai => arr2.includes(ai) );
Unlike of it: Must contains all values.
let allFounded = arr2.every( ai => arr1.includes(ai) );
Hope, will be helpful.
If you're not opposed to using a libray, http://underscorejs.org/ has an intersection method, which can simplify this:
var _ = require('underscore');
var target = [ 'apple', 'orange', 'banana'];
var fruit2 = [ 'apple', 'orange', 'mango'];
var fruit3 = [ 'mango', 'lemon', 'pineapple'];
var fruit4 = [ 'orange', 'lemon', 'grapes'];
console.log(_.intersection(target, fruit2)); //returns [apple, orange]
console.log(_.intersection(target, fruit3)); //returns []
console.log(_.intersection(target, fruit4)); //returns [orange]
The intersection function will return a new array with the items that it matched and if not matches it returns empty array.
ES6 (fastest)
const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
a.some(v=> b.indexOf(v) !== -1)
ES2016
const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
a.some(v => b.includes(v));
Underscore
const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
_.intersection(a, b)
DEMO: https://jsfiddle.net/r257wuv5/
jsPerf: https://jsperf.com/array-contains-any-element-of-another-array
If you don't need type coercion (because of the use of indexOf), you could try something like the following:
var arr = [1, 2, 3];
var check = [3, 4];
var found = false;
for (var i = 0; i < check.length; i++) {
if (arr.indexOf(check[i]) > -1) {
found = true;
break;
}
}
console.log(found);
Where arr contains the target items. At the end, found will show if the second array had at least one match against the target.
Of course, you can swap out numbers for anything you want to use - strings are fine, like your example.
And in my specific example, the result should be true because the second array's 3 exists in the target.
UPDATE:
Here's how I'd organize it into a function (with some minor changes from before):
var anyMatchInArray = (function () {
"use strict";
var targetArray, func;
targetArray = ["apple", "banana", "orange"];
func = function (checkerArray) {
var found = false;
for (var i = 0, j = checkerArray.length; !found && i < j; i++) {
if (targetArray.indexOf(checkerArray[i]) > -1) {
found = true;
}
}
return found;
};
return func;
}());
DEMO: http://jsfiddle.net/u8Bzt/
In this case, the function could be modified to have targetArray be passed in as an argument instead of hardcoded in the closure.
UPDATE2:
While my solution above may work and be (hopefully more) readable, I believe the "better" way to handle the concept I described is to do something a little differently. The "problem" with the above solution is that the indexOf inside the loop causes the target array to be looped over completely for every item in the other array. This can easily be "fixed" by using a "lookup" (a map...a JavaScript object literal). This allows two simple loops, over each array. Here's an example:
var anyMatchInArray = function (target, toMatch) {
"use strict";
var found, targetMap, i, j, cur;
found = false;
targetMap = {};
// Put all values in the `target` array into a map, where
// the keys are the values from the array
for (i = 0, j = target.length; i < j; i++) {
cur = target[i];
targetMap[cur] = true;
}
// Loop over all items in the `toMatch` array and see if any of
// their values are in the map from before
for (i = 0, j = toMatch.length; !found && (i < j); i++) {
cur = toMatch[i];
found = !!targetMap[cur];
// If found, `targetMap[cur]` will return true, otherwise it
// will return `undefined`...that's what the `!!` is for
}
return found;
};
DEMO: http://jsfiddle.net/5Lv9v/
The downside to this solution is that only numbers and strings (and booleans) can be used (correctly), because the values are (implicitly) converted to strings and set as the keys to the lookup map. This isn't exactly good/possible/easily done for non-literal values.
Using filter/indexOf:
function containsAny(source,target)
{
var result = source.filter(function(item){ return target.indexOf(item) > -1});
return (result.length > 0);
}
//results
var fruits = ["apple","banana","orange"];
console.log(containsAny(fruits,["apple","grape"]));
console.log(containsAny(fruits,["apple","banana","pineapple"]));
console.log(containsAny(fruits,["grape", "pineapple"]));
You could use lodash and do:
_.intersection(originalTarget, arrayToCheck).length > 0
Set intersection is done on both collections producing an array of identical elements.
const areCommonElements = (arr1, arr2) => {
const arr2Set = new Set(arr2);
return arr1.some(el => arr2Set.has(el));
};
Or you can even have a better performance if you first find out which of these two arrays is longer and making Set out for the longest array, while applying some method on the shortest one:
const areCommonElements = (arr1, arr2) => {
const [shortArr, longArr] = (arr1.length < arr2.length) ? [arr1, arr2] : [arr2, arr1];
const longArrSet = new Set(longArr);
return shortArr.some(el => longArrSet.has(el));
};
I wrote 3 solutions. Essentially they do the same. They return true as soon as they get true. I wrote the 3 solutions just for showing 3 different way to do things. Now, it depends what you like more. You can use performance.now() to check the performance of one solution or the other. In my solutions I'm also checking which array is the biggest and which one is the smallest to make the operations more efficient.
The 3rd solution may not be the cutest but is efficient. I decided to add it because in some coding interviews you are not allowed to use built-in methods.
Lastly, sure...we can come up with a solution with 2 NESTED for loops (the brute force way) but you want to avoid that because the time complexity is bad O(n^2).
Note:
instead of using .includes() like some other people did, you can use
.indexOf(). if you do just check if the value is bigger than 0. If
the value doesn't exist will give you -1. if it does exist, it will give you
greater than 0.
indexOf() vs includes()
Which one has better performance? indexOf() for a little bit, but includes is more readable in my opinion.
If I'm not mistaken .includes() and indexOf() use loops behind the scene, so you will be at O(n^2) when using them with .some().
USING loop
const compareArraysWithIncludes = (arr1, arr2) => {
const [smallArray, bigArray] =
arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];
for (let i = 0; i < smallArray.length; i++) {
return bigArray.includes(smallArray[i]);
}
return false;
};
USING .some()
const compareArraysWithSome = (arr1, arr2) => {
const [smallArray, bigArray] =
arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];
return smallArray.some(c => bigArray.includes(c));
};
USING MAPS Time complexity O(2n)=>O(n)
const compararArraysUsingObjs = (arr1, arr2) => {
const map = {};
const [smallArray, bigArray] =
arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];
for (let i = 0; i < smallArray.length; i++) {
if (!map[smallArray[i]]) {
map[smallArray[i]] = true;
}
}
for (let i = 0; i < bigArray.length; i++) {
if (map[bigArray[i]]) {
return true;
}
}
return false;
};
Code in my:
stackblitz
I'm not an expert in performance nor BigO so if something that I said is wrong let me know.
You can use a nested Array.prototype.some call. This has the benefit that it will bail at the first match instead of other solutions that will run through the full nested loop.
eg.
var arr = [1, 2, 3];
var match = [2, 4];
var hasMatch = arr.some(a => match.some(m => a === m));
I found this short and sweet syntax to match all or some elements between two arrays. For example
// OR operation. find if any of array2 elements exists in array1. This will return as soon as there is a first match as some method breaks when function returns TRUE
let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'b'];
console.log(array2.some(ele => array1.includes(ele)));
// prints TRUE
// AND operation. find if all of array2 elements exists in array1. This will return as soon as there is a no first match as some method breaks when function returns TRUE
let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'x'];
console.log(!array2.some(ele => !array1.includes(ele)));
// prints FALSE
Hope that helps someone in future!
Just one more solution
var a1 = [1, 2, 3, 4, 5]
var a2 = [2, 4]
Check if a1 contain all element of a2
var result = a1.filter(e => a2.indexOf(e) !== -1).length === a2.length
console.log(result)
What about using a combination of some/findIndex and indexOf?
So something like this:
var array1 = ["apple","banana","orange"];
var array2 = ["grape", "pineapple"];
var found = array1.some(function(v) { return array2.indexOf(v) != -1; });
To make it more readable you could add this functionality to the Array object itself.
Array.prototype.indexOfAny = function (array) {
return this.findIndex(function(v) { return array.indexOf(v) != -1; });
}
Array.prototype.containsAny = function (array) {
return this.indexOfAny(array) != -1;
}
Note: If you'd want to do something with a predicate you could replace the inner indexOf with another findIndex and a predicate
Here is an interesting case I thought I should share.
Let's say that you have an array of objects and an array of selected filters.
let arr = [
{ id: 'x', tags: ['foo'] },
{ id: 'y', tags: ['foo', 'bar'] },
{ id: 'z', tags: ['baz'] }
];
const filters = ['foo'];
To apply the selected filters to this structure we can
if (filters.length > 0)
arr = arr.filter(obj =>
obj.tags.some(tag => filters.includes(tag))
);
// [
// { id: 'x', tags: ['foo'] },
// { id: 'y', tags: ['foo', 'bar'] }
// ]
Good perfomance solution:
We should transform one of arrays to object.
const contains = (arr1, mainObj) => arr1.some(el => el in mainObj);
const includes = (arr1, mainObj) => arr1.every(el => el in mainObj);
Usage:
const mainList = ["apple", "banana", "orange"];
// We make object from array, you can use your solution to make it
const main = Object.fromEntries(mainList.map(key => [key, true]));
contains(["apple","grape"], main) // => true
contains(["apple","banana","pineapple"], main) // => true
contains(["grape", "pineapple"], main) // => false
includes(["apple", "grape"], main) // => false
includes(["banana", "apple"], main) // => true
you can face with some disadvantage of checking by in operator (eg 'toString' in {} // => true), so you can change solution to obj[key] checker
Adding to Array Prototype
Disclaimer: Many would strongly advise against this. The only time it'd really be a problem was if a library added a prototype function with the same name (that behaved differently) or something like that.
Code:
Array.prototype.containsAny = function(arr) {
return this.some(
(v) => (arr.indexOf(v) >= 0)
)
}
Without using big arrow functions:
Array.prototype.containsAny = function(arr) {
return this.some(function (v) {
return arr.indexOf(v) >= 0
})
}
Usage
var a = ["a","b"]
console.log(a.containsAny(["b","z"])) // Outputs true
console.log(a.containsAny(["z"])) // Outputs false
My solution applies Array.prototype.some() and Array.prototype.includes() array helpers which do their job pretty efficient as well
ES6
const originalFruits = ["apple","banana","orange"];
const fruits1 = ["apple","banana","pineapple"];
const fruits2 = ["grape", "pineapple"];
const commonFruits = (myFruitsArr, otherFruitsArr) => {
return myFruitsArr.some(fruit => otherFruitsArr.includes(fruit))
}
console.log(commonFruits(originalFruits, fruits1)) //returns true;
console.log(commonFruits(originalFruits, fruits2)) //returns false;
When I looked at your answers, I could not find the answer I wanted.
I did something myself and I want to share this with you.
It will be true only if the words entered (array) are correct.
function contains(a,b) {
let counter = 0;
for(var i = 0; i < b.length; i++) {;
if(a.includes(b[i])) counter++;
}
if(counter === b.length) return true;
return false;
}
let main_array = ['foo','bar','baz'];
let sub_array_a = ['foo','foobar'];
let sub_array_b = ['foo','bar'];
console.log(contains(main_array, sub_array_a)); // returns false
console.log(contains(main_array,sub_array_b )); // returns true
Array .filter() with a nested call to .find() will return all elements in the first array that are members of the second array. Check the length of the returned array to determine if any of the second array were in the first array.
getCommonItems(firstArray, secondArray) {
return firstArray.filter((firstArrayItem) => {
return secondArray.find((secondArrayItem) => {
return firstArrayItem === secondArrayItem;
});
});
}
It can be done by simply iterating across the main array and check whether other array contains any of the target element or not.
Try this:
function Check(A) {
var myarr = ["apple", "banana", "orange"];
var i, j;
var totalmatches = 0;
for (i = 0; i < myarr.length; i++) {
for (j = 0; j < A.length; ++j) {
if (myarr[i] == A[j]) {
totalmatches++;
}
}
}
if (totalmatches > 0) {
return true;
} else {
return false;
}
}
var fruits1 = new Array("apple", "grape");
alert(Check(fruits1));
var fruits2 = new Array("apple", "banana", "pineapple");
alert(Check(fruits2));
var fruits3 = new Array("grape", "pineapple");
alert(Check(fruits3));
DEMO at JSFIDDLE
Not sure how efficient this might be in terms of performance, but this is what I use using array destructuring to keep everything nice and short:
const shareElements = (arr1, arr2) => {
const typeArr = [...arr1, ...arr2]
const typeSet = new Set(typeArr)
return typeArr.length > typeSet.size
}
Since sets cannot have duplicate elements while arrays can, combining both input arrays, converting it to a set, and comparing the set size and array length would tell you if they share any elements.
With underscorejs
var a1 = [1,2,3];
var a2 = [1,2];
_.every(a1, function(e){ return _.include(a2, e); } ); //=> false
_.every(a2, function(e){ return _.include(a1, e); } ); //=> true
Vanilla JS with partial matching & case insensitive
The problem with some previous approaches is that they require an exact match of every word. But, What if you want to provide results for partial matches?
function search(arrayToSearch, wordsToSearch) {
arrayToSearch.filter(v =>
wordsToSearch.every(w =>
v.toLowerCase().split(" ").
reduce((isIn, h) => isIn || String(h).indexOf(w) >= 0, false)
)
)
}
//Usage
var myArray = ["Attach tag", "Attaching tags", "Blah blah blah"];
var searchText = "Tag attach";
var searchArr = searchText.toLowerCase().split(" "); //["tag", "attach"]
var matches = search(myArray, searchArr);
//Will return
//["Attach tag", "Attaching tags"]
This is useful when you want to provide a search box where users type words and the results can have those words in any order, position and case.
Update #Paul Grimshaw answer, use includes insteed of indexOf for more readable
let found = arr1.some(r=> arr2.indexOf(r) >= 0)
let found = arr1.some(r=> arr2.includes(r))
A short way of writing this:
const found = arr1.some(arr2.includes)
I came up with a solution in node using underscore js like this:
var checkRole = _.intersection(['A','B'], ['A','B','C']);
if(!_.isEmpty(checkRole)) {
next();
}
You are looking for intersection between the two arrays. And you have two major intersection types: 'every' and 'some'. Let me give you good examples:
EVERY
let brands1 = ['Ford', 'Kia', 'VW', 'Audi'];
let brands2 = ['Audi', 'Kia'];
// Find 'every' brand intersection.
// Meaning all elements inside 'brands2' must be present in 'brands1':
let intersectionEvery = brands2.every( brand => brands1.includes(brand) );
if (intersectionEvery) {
const differenceList = brands1.filter(brand => !brands2.includes(brand));
console.log('difference list:', differenceList);
const commonList = brands1.filter(brand => brands2.includes(brand));
console.log('common list:', commonList);
}
If condition is not met (like if you put 'Mercedes' in brands2) then 'intersectionEvery' won't be satisfied - will be bool false.
If condition is met it will log ["Ford", "VW"] as difference and ["Kia", "Audi"] as common list.
Sandbox: https://jsfiddle.net/bqmg14t6/
SOME
let brands1 = ['Ford', 'Kia', 'VW', 'Audi'];
let brands2 = ['Audi', 'Kia', 'Mercedes', 'Land Rover'];
// Find 'some' brand intersection.
// Meaning some elements inside 'brands2' must be also present in 'brands1':
let intersectionSome = brands2.some( brand => brands1.includes(brand) );
if (intersectionSome) {
const differenceList = brands1.filter(brand => !brands2.includes(brand));
console.log('difference list:', differenceList);
const commonList = brands1.filter(brand => brands2.includes(brand));
console.log('common list:', commonList);
}
Here we are looking for some common brands, not necessarily all.
It will log ["Ford", "VW"] as difference and ["Kia", "Audi"] as common brands.
Sandbox: https://jsfiddle.net/zkq9j3Lh/
Personally, I would use the following function:
var arrayContains = function(array, toMatch) {
var arrayAsString = array.toString();
return (arrayAsString.indexOf(','+toMatch+',') >-1);
}
The "toString()" method will always use commas to separate the values. Will only really work with primitive types.
console.log("searching Array: "+finding_array);
console.log("searching in:"+reference_array);
var check_match_counter = 0;
for (var j = finding_array.length - 1; j >= 0; j--)
{
if(reference_array.indexOf(finding_array[j]) > 0)
{
check_match_counter = check_match_counter + 1;
}
}
var match = (check_match_counter > 0) ? true : false;
console.log("Final result:"+match);
Problem:
Given two arrays of strings, for every string in list (query), determine how many anagrams of it are in the other list (dictionary).
It should return an array of integers.
Example:
query = ["a", "nark", "bs", "hack", "stair"]
dictionary = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits']
The answer would be [2, 2, 0, 3, 1] since query[0] ('a') has 2 anagrams in dictionary: 'a' and 'a' and so on...
This was the code I came up with:
function sortArray(array) {
let answer = [];
for(let i = 0; i< array.length ; i++) {
let data = array[i].split('').sort().join('');
answer.push(data);
}
return answer;
}
function stringAnagram(dictionary, query) {
// Write your code here
let sortedDict = sortArray(dictionary);
let sortedQuery = sortArray(query);
let answer = [];
console.log(sortedDict.length);
console.log(sortedQuery.length);
sortedQuery.map(data => {
let i = 0;
sortedDict.forEach(dictData => {
if(data === dictData)
i++;
})
answer.push(i);
})
return answer;
}
However it is returning timeout error for longer test cases. Need some help optimizing it. Any suggestions? I'm trying to achieve it in JavaScript.
You may want to avoid using (expensive) Array.prototype.sort() to detect anagram and give your anagram detection algorithm as much shortcuts as possible.
So, if assume, anagrams should be the strings of the same length with the same count of the same characters, you may go something, like that:
const query = ["a", "nark", "bs", "hack", "stair"],
dictionary = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'],
charCount = s => [...s].reduce((acc,c) =>
(acc[c]=(acc[c]||0)+1, acc), {}),
areAnagrams = (s1, s2) => {
if(s1.length != s2.length) return false
const s1CharCount = charCount(s1),
s2CharCount = charCount(s2),
result = Object
.keys(s1CharCount)
.every(char =>
s2CharCount[char] == s1CharCount[char])
return result
},
outcome = query.map(word =>
dictionary
.filter(_word => areAnagrams(word, _word))
.length
)
console.log(outcome)
Slightly more verbose way of doing it - but it works and makes sense to me - for each word in the original array, find the words in the target array that are the same length and then count those that are anagrams of the original word (an anagram is another word made up of the same letters in any order).
So the steps are -
Iterate over the firat array and for each word - filter the target array to get all words that are the same length as that word (potentialAnagrams)
Then iterate over that potentialAnagrams array and pass each word to a function that checks if all the letters and only the letters in the original word are present (in the given example - that would be [2, 2, 0, 3, 1]
Add up all anagrams of the word and pass the count to an array that is logged as the final result.
const queryArr = ["a", "nark", "bs", "hack", "stair"];
const dictionaryArr = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'];
let anagramsArr = [];
queryArr.forEach(function(query){
let anagramsCount = 0
const potentialAnagrams = dictionaryArr.filter(el => el.length === query.length);
potentialAnagrams.forEach(function(potentialAnagram){
if(isAnagram(query,potentialAnagram)){
anagramsCount++
}
})
anagramsArr.push(anagramsCount);
})
function isAnagram(word1, word2){
let count = 0;
const word1Arr = word1.split('');
const word2Arr = word2.split('');
if( word1Arr.length !== word2Arr.length) {
return 'Invalid data - words 1 and 2 are of different lengths';
}
word1Arr.forEach(function(letter){
if(word2.indexOf(letter) !== -1) {
count++
}
})
return count === word1Arr.length
}
console.log(isAnagram('ab', 'bab')); //gives 'Invalid data - words 1 and 2 are of different lengths';
console.log(anagramsArr); //gives [2, 2, 0, 3,1];
I have an array = [A,1,0,1,0,1,B,1,0,0,1,A,1]
I need to split this array into multiple arrays. The split will occur at the "A" or "B" position as seen in the new arrays below. The names of the new arrays use the string "group" plus an incremented number starting with 1 or 0.
The end result should look like:
group1 = [A,1,0,1,0,1]
group2 = [B,1,0,0,1]
group3 = [A,1]
I can get the section of the array I need by creating an array (arrTemp), so I can store the positions (indexes) and later use slice() to get the sections I want (A,1,0,1,0,1), (A,1,0,0,1), and (A,1). But I don't know how to store the results of my slice()'s in arrays with unique names incremented by 1.
This is what I have tried so far:
var arr = [A,1,0,1,0,1,B,1,0,0,1,A,1];
arr.forEach(myFunction)
function myFunction(item, index) {
if ((item=="A") || (item=="B")) {
arrTemp.push(index);
arrTemp=arrTemp; //not sure I need this. I did this so it array would be global
}
}
for (var i = 0; i < arr.length; i++){
sectArray = arr.slice(arrTemp[i]+1,arrTemp[i + 1])
'group' + [i] = [arrTemp[i],sectArray]; //here is my problem.
}
It seems like you're trying to dynamically create variables. That seems tricky and probably won't work. What you should probably have is some collection of results. Probably a parent array that holds all of them.
For example:
var containerArray = [];
Then:
for (var i = 0; i < arr.length; i++){
sectArray = arr.slice(arrTemp[i]+1,arrTemp[i + 1])
containerArray[i] = [arrTemp[i],sectArray];
}
Now containerArray will have all of your stuff. You can also do this with an object:
var containerObject = {};
And the same thing after.
you only need one loop here, keep an empty temp array, iterate over arr and keep pushing elements in temp each time you see 'A' or 'B' push temp to final array, and at last push temp once more into final array because last section will be left.
var arr = ['A',1,0,1,0,1,'B',1,0,0,1,'A',1];
var temp = [];
var sectArray = [];
arr.forEach(myFunction)
function myFunction(item, index) {
if (((item=="A") || (item=="B")) && temp.length) {
sectArray.push(temp);
temp = [item];
}else{
temp.push(item);
}
}
sectArray.push(temp);
console.log(sectArray);
Check this solution that use a combination of string and array methods:
var data = ['A',1,0,1,0,1,'B',1,0,0,1,'A',1];
var results = data.toString().split(/(?=[a-zA-Z]+)/)
.map(function(value){
return value.split(',').filter(function (item) {
return item.length ? true: false;
})
})
.map(function(item) {
return item.map(function (value) {
return isNaN(parseInt(value)) ? value : parseInt(value);
})
});
console.log(results);
// results = [["A", 1, 0, 1, 0, 1], ["B", 1, 0, 0, 1], ["A", 1]]
Another solution using Array#reduce function.
var x = ["A", 1, 0, 1, 0, 1, "B", 1, 0, 0, 1, "A", 1];
function reformat(arr) {
var smallArrCounter = 0;
return arr.reduce(function (acc, item) {
if (item === "A" || item === "B") {
acc["group" + (++smallArrCounter)] = [item];
} else {
acc["group" + smallArrCounter].push(item);
}
return acc;
}, {});
}
var result = reformat(x);
console.log(result.group1); // ["A", 1, 0, 1, 0, 1]
console.log(result.group2); // ["B", 1, 0, 0, 1]
console.log(result.group3); // ["A", 1]
There may be a more performant approach that doesn't require two iterations of the array, but my thought is:
Determine the indices of the group delimiters (characters)
Slice the array into groups based on those delimiters, using either the next index as the end, or arr.length if slicing the last group
This has the assumption that the array delimiters may not be known in advance.
const charIndices = [];
const groups = [];
const arr = ['A',1,0,1,0,1,'B',1,0,0,1,'A',1];
// get the indices of the characters
arr.forEach((v, i) => ('' + v).match(/[A-Z]+/) ? charIndices.push(i) : undefined);
// use the found indices to split into groups
charIndices.reduce((a, b, i) => {
a.push(arr.slice(b, charIndices[i+1] ? charIndices[i+1]-1 : arr.length));
return a;
}, groups);
console.log(groups);
I have a target array ["apple","banana","orange"], and I want to check if other arrays contain any one of the target array elements.
For example:
["apple","grape"] //returns true;
["apple","banana","pineapple"] //returns true;
["grape", "pineapple"] //returns false;
How can I do it in JavaScript?
Vanilla JS
ES2016:
const found = arr1.some(r=> arr2.includes(r))
ES6:
const found = arr1.some(r=> arr2.indexOf(r) >= 0)
How it works
some(..) checks each element of the array against a test function and returns true if any element of the array passes the test function, otherwise, it returns false. indexOf(..) >= 0 and includes(..) both return true if the given argument is present in the array.
vanilla js
/**
* #description determine if an array contains one or more items from another array.
* #param {array} haystack the array to search.
* #param {array} arr the array providing items to check for in the haystack.
* #return {boolean} true|false if haystack contains at least one item from arr.
*/
var findOne = function (haystack, arr) {
return arr.some(function (v) {
return haystack.indexOf(v) >= 0;
});
};
As noted by #loganfsmyth you can shorten it in ES2016 to
/**
* #description determine if an array contains one or more items from another array.
* #param {array} haystack the array to search.
* #param {array} arr the array providing items to check for in the haystack.
* #return {boolean} true|false if haystack contains at least one item from arr.
*/
const findOne = (haystack, arr) => {
return arr.some(v => haystack.includes(v));
};
or simply as arr.some(v => haystack.includes(v));
If you want to determine if the array has all the items from the other array, replace some() to every()
or as arr.every(v => haystack.includes(v));
ES6 solution:
let arr1 = [1, 2, 3];
let arr2 = [2, 3];
let isFounded = arr1.some( ai => arr2.includes(ai) );
Unlike of it: Must contains all values.
let allFounded = arr2.every( ai => arr1.includes(ai) );
Hope, will be helpful.
If you're not opposed to using a libray, http://underscorejs.org/ has an intersection method, which can simplify this:
var _ = require('underscore');
var target = [ 'apple', 'orange', 'banana'];
var fruit2 = [ 'apple', 'orange', 'mango'];
var fruit3 = [ 'mango', 'lemon', 'pineapple'];
var fruit4 = [ 'orange', 'lemon', 'grapes'];
console.log(_.intersection(target, fruit2)); //returns [apple, orange]
console.log(_.intersection(target, fruit3)); //returns []
console.log(_.intersection(target, fruit4)); //returns [orange]
The intersection function will return a new array with the items that it matched and if not matches it returns empty array.
ES6 (fastest)
const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
a.some(v=> b.indexOf(v) !== -1)
ES2016
const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
a.some(v => b.includes(v));
Underscore
const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
_.intersection(a, b)
DEMO: https://jsfiddle.net/r257wuv5/
jsPerf: https://jsperf.com/array-contains-any-element-of-another-array
If you don't need type coercion (because of the use of indexOf), you could try something like the following:
var arr = [1, 2, 3];
var check = [3, 4];
var found = false;
for (var i = 0; i < check.length; i++) {
if (arr.indexOf(check[i]) > -1) {
found = true;
break;
}
}
console.log(found);
Where arr contains the target items. At the end, found will show if the second array had at least one match against the target.
Of course, you can swap out numbers for anything you want to use - strings are fine, like your example.
And in my specific example, the result should be true because the second array's 3 exists in the target.
UPDATE:
Here's how I'd organize it into a function (with some minor changes from before):
var anyMatchInArray = (function () {
"use strict";
var targetArray, func;
targetArray = ["apple", "banana", "orange"];
func = function (checkerArray) {
var found = false;
for (var i = 0, j = checkerArray.length; !found && i < j; i++) {
if (targetArray.indexOf(checkerArray[i]) > -1) {
found = true;
}
}
return found;
};
return func;
}());
DEMO: http://jsfiddle.net/u8Bzt/
In this case, the function could be modified to have targetArray be passed in as an argument instead of hardcoded in the closure.
UPDATE2:
While my solution above may work and be (hopefully more) readable, I believe the "better" way to handle the concept I described is to do something a little differently. The "problem" with the above solution is that the indexOf inside the loop causes the target array to be looped over completely for every item in the other array. This can easily be "fixed" by using a "lookup" (a map...a JavaScript object literal). This allows two simple loops, over each array. Here's an example:
var anyMatchInArray = function (target, toMatch) {
"use strict";
var found, targetMap, i, j, cur;
found = false;
targetMap = {};
// Put all values in the `target` array into a map, where
// the keys are the values from the array
for (i = 0, j = target.length; i < j; i++) {
cur = target[i];
targetMap[cur] = true;
}
// Loop over all items in the `toMatch` array and see if any of
// their values are in the map from before
for (i = 0, j = toMatch.length; !found && (i < j); i++) {
cur = toMatch[i];
found = !!targetMap[cur];
// If found, `targetMap[cur]` will return true, otherwise it
// will return `undefined`...that's what the `!!` is for
}
return found;
};
DEMO: http://jsfiddle.net/5Lv9v/
The downside to this solution is that only numbers and strings (and booleans) can be used (correctly), because the values are (implicitly) converted to strings and set as the keys to the lookup map. This isn't exactly good/possible/easily done for non-literal values.
Using filter/indexOf:
function containsAny(source,target)
{
var result = source.filter(function(item){ return target.indexOf(item) > -1});
return (result.length > 0);
}
//results
var fruits = ["apple","banana","orange"];
console.log(containsAny(fruits,["apple","grape"]));
console.log(containsAny(fruits,["apple","banana","pineapple"]));
console.log(containsAny(fruits,["grape", "pineapple"]));
You could use lodash and do:
_.intersection(originalTarget, arrayToCheck).length > 0
Set intersection is done on both collections producing an array of identical elements.
const areCommonElements = (arr1, arr2) => {
const arr2Set = new Set(arr2);
return arr1.some(el => arr2Set.has(el));
};
Or you can even have a better performance if you first find out which of these two arrays is longer and making Set out for the longest array, while applying some method on the shortest one:
const areCommonElements = (arr1, arr2) => {
const [shortArr, longArr] = (arr1.length < arr2.length) ? [arr1, arr2] : [arr2, arr1];
const longArrSet = new Set(longArr);
return shortArr.some(el => longArrSet.has(el));
};
I wrote 3 solutions. Essentially they do the same. They return true as soon as they get true. I wrote the 3 solutions just for showing 3 different way to do things. Now, it depends what you like more. You can use performance.now() to check the performance of one solution or the other. In my solutions I'm also checking which array is the biggest and which one is the smallest to make the operations more efficient.
The 3rd solution may not be the cutest but is efficient. I decided to add it because in some coding interviews you are not allowed to use built-in methods.
Lastly, sure...we can come up with a solution with 2 NESTED for loops (the brute force way) but you want to avoid that because the time complexity is bad O(n^2).
Note:
instead of using .includes() like some other people did, you can use
.indexOf(). if you do just check if the value is bigger than 0. If
the value doesn't exist will give you -1. if it does exist, it will give you
greater than 0.
indexOf() vs includes()
Which one has better performance? indexOf() for a little bit, but includes is more readable in my opinion.
If I'm not mistaken .includes() and indexOf() use loops behind the scene, so you will be at O(n^2) when using them with .some().
USING loop
const compareArraysWithIncludes = (arr1, arr2) => {
const [smallArray, bigArray] =
arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];
for (let i = 0; i < smallArray.length; i++) {
return bigArray.includes(smallArray[i]);
}
return false;
};
USING .some()
const compareArraysWithSome = (arr1, arr2) => {
const [smallArray, bigArray] =
arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];
return smallArray.some(c => bigArray.includes(c));
};
USING MAPS Time complexity O(2n)=>O(n)
const compararArraysUsingObjs = (arr1, arr2) => {
const map = {};
const [smallArray, bigArray] =
arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];
for (let i = 0; i < smallArray.length; i++) {
if (!map[smallArray[i]]) {
map[smallArray[i]] = true;
}
}
for (let i = 0; i < bigArray.length; i++) {
if (map[bigArray[i]]) {
return true;
}
}
return false;
};
Code in my:
stackblitz
I'm not an expert in performance nor BigO so if something that I said is wrong let me know.
You can use a nested Array.prototype.some call. This has the benefit that it will bail at the first match instead of other solutions that will run through the full nested loop.
eg.
var arr = [1, 2, 3];
var match = [2, 4];
var hasMatch = arr.some(a => match.some(m => a === m));
I found this short and sweet syntax to match all or some elements between two arrays. For example
// OR operation. find if any of array2 elements exists in array1. This will return as soon as there is a first match as some method breaks when function returns TRUE
let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'b'];
console.log(array2.some(ele => array1.includes(ele)));
// prints TRUE
// AND operation. find if all of array2 elements exists in array1. This will return as soon as there is a no first match as some method breaks when function returns TRUE
let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'x'];
console.log(!array2.some(ele => !array1.includes(ele)));
// prints FALSE
Hope that helps someone in future!
Just one more solution
var a1 = [1, 2, 3, 4, 5]
var a2 = [2, 4]
Check if a1 contain all element of a2
var result = a1.filter(e => a2.indexOf(e) !== -1).length === a2.length
console.log(result)
What about using a combination of some/findIndex and indexOf?
So something like this:
var array1 = ["apple","banana","orange"];
var array2 = ["grape", "pineapple"];
var found = array1.some(function(v) { return array2.indexOf(v) != -1; });
To make it more readable you could add this functionality to the Array object itself.
Array.prototype.indexOfAny = function (array) {
return this.findIndex(function(v) { return array.indexOf(v) != -1; });
}
Array.prototype.containsAny = function (array) {
return this.indexOfAny(array) != -1;
}
Note: If you'd want to do something with a predicate you could replace the inner indexOf with another findIndex and a predicate
Here is an interesting case I thought I should share.
Let's say that you have an array of objects and an array of selected filters.
let arr = [
{ id: 'x', tags: ['foo'] },
{ id: 'y', tags: ['foo', 'bar'] },
{ id: 'z', tags: ['baz'] }
];
const filters = ['foo'];
To apply the selected filters to this structure we can
if (filters.length > 0)
arr = arr.filter(obj =>
obj.tags.some(tag => filters.includes(tag))
);
// [
// { id: 'x', tags: ['foo'] },
// { id: 'y', tags: ['foo', 'bar'] }
// ]
Good perfomance solution:
We should transform one of arrays to object.
const contains = (arr1, mainObj) => arr1.some(el => el in mainObj);
const includes = (arr1, mainObj) => arr1.every(el => el in mainObj);
Usage:
const mainList = ["apple", "banana", "orange"];
// We make object from array, you can use your solution to make it
const main = Object.fromEntries(mainList.map(key => [key, true]));
contains(["apple","grape"], main) // => true
contains(["apple","banana","pineapple"], main) // => true
contains(["grape", "pineapple"], main) // => false
includes(["apple", "grape"], main) // => false
includes(["banana", "apple"], main) // => true
you can face with some disadvantage of checking by in operator (eg 'toString' in {} // => true), so you can change solution to obj[key] checker
Adding to Array Prototype
Disclaimer: Many would strongly advise against this. The only time it'd really be a problem was if a library added a prototype function with the same name (that behaved differently) or something like that.
Code:
Array.prototype.containsAny = function(arr) {
return this.some(
(v) => (arr.indexOf(v) >= 0)
)
}
Without using big arrow functions:
Array.prototype.containsAny = function(arr) {
return this.some(function (v) {
return arr.indexOf(v) >= 0
})
}
Usage
var a = ["a","b"]
console.log(a.containsAny(["b","z"])) // Outputs true
console.log(a.containsAny(["z"])) // Outputs false
My solution applies Array.prototype.some() and Array.prototype.includes() array helpers which do their job pretty efficient as well
ES6
const originalFruits = ["apple","banana","orange"];
const fruits1 = ["apple","banana","pineapple"];
const fruits2 = ["grape", "pineapple"];
const commonFruits = (myFruitsArr, otherFruitsArr) => {
return myFruitsArr.some(fruit => otherFruitsArr.includes(fruit))
}
console.log(commonFruits(originalFruits, fruits1)) //returns true;
console.log(commonFruits(originalFruits, fruits2)) //returns false;
When I looked at your answers, I could not find the answer I wanted.
I did something myself and I want to share this with you.
It will be true only if the words entered (array) are correct.
function contains(a,b) {
let counter = 0;
for(var i = 0; i < b.length; i++) {;
if(a.includes(b[i])) counter++;
}
if(counter === b.length) return true;
return false;
}
let main_array = ['foo','bar','baz'];
let sub_array_a = ['foo','foobar'];
let sub_array_b = ['foo','bar'];
console.log(contains(main_array, sub_array_a)); // returns false
console.log(contains(main_array,sub_array_b )); // returns true
Array .filter() with a nested call to .find() will return all elements in the first array that are members of the second array. Check the length of the returned array to determine if any of the second array were in the first array.
getCommonItems(firstArray, secondArray) {
return firstArray.filter((firstArrayItem) => {
return secondArray.find((secondArrayItem) => {
return firstArrayItem === secondArrayItem;
});
});
}
It can be done by simply iterating across the main array and check whether other array contains any of the target element or not.
Try this:
function Check(A) {
var myarr = ["apple", "banana", "orange"];
var i, j;
var totalmatches = 0;
for (i = 0; i < myarr.length; i++) {
for (j = 0; j < A.length; ++j) {
if (myarr[i] == A[j]) {
totalmatches++;
}
}
}
if (totalmatches > 0) {
return true;
} else {
return false;
}
}
var fruits1 = new Array("apple", "grape");
alert(Check(fruits1));
var fruits2 = new Array("apple", "banana", "pineapple");
alert(Check(fruits2));
var fruits3 = new Array("grape", "pineapple");
alert(Check(fruits3));
DEMO at JSFIDDLE
Not sure how efficient this might be in terms of performance, but this is what I use using array destructuring to keep everything nice and short:
const shareElements = (arr1, arr2) => {
const typeArr = [...arr1, ...arr2]
const typeSet = new Set(typeArr)
return typeArr.length > typeSet.size
}
Since sets cannot have duplicate elements while arrays can, combining both input arrays, converting it to a set, and comparing the set size and array length would tell you if they share any elements.
A short way of writing this:
const found = arr1.some(arr2.includes)
With underscorejs
var a1 = [1,2,3];
var a2 = [1,2];
_.every(a1, function(e){ return _.include(a2, e); } ); //=> false
_.every(a2, function(e){ return _.include(a1, e); } ); //=> true
Vanilla JS with partial matching & case insensitive
The problem with some previous approaches is that they require an exact match of every word. But, What if you want to provide results for partial matches?
function search(arrayToSearch, wordsToSearch) {
arrayToSearch.filter(v =>
wordsToSearch.every(w =>
v.toLowerCase().split(" ").
reduce((isIn, h) => isIn || String(h).indexOf(w) >= 0, false)
)
)
}
//Usage
var myArray = ["Attach tag", "Attaching tags", "Blah blah blah"];
var searchText = "Tag attach";
var searchArr = searchText.toLowerCase().split(" "); //["tag", "attach"]
var matches = search(myArray, searchArr);
//Will return
//["Attach tag", "Attaching tags"]
This is useful when you want to provide a search box where users type words and the results can have those words in any order, position and case.
Update #Paul Grimshaw answer, use includes insteed of indexOf for more readable
let found = arr1.some(r=> arr2.indexOf(r) >= 0)
let found = arr1.some(r=> arr2.includes(r))
I came up with a solution in node using underscore js like this:
var checkRole = _.intersection(['A','B'], ['A','B','C']);
if(!_.isEmpty(checkRole)) {
next();
}
You are looking for intersection between the two arrays. And you have two major intersection types: 'every' and 'some'. Let me give you good examples:
EVERY
let brands1 = ['Ford', 'Kia', 'VW', 'Audi'];
let brands2 = ['Audi', 'Kia'];
// Find 'every' brand intersection.
// Meaning all elements inside 'brands2' must be present in 'brands1':
let intersectionEvery = brands2.every( brand => brands1.includes(brand) );
if (intersectionEvery) {
const differenceList = brands1.filter(brand => !brands2.includes(brand));
console.log('difference list:', differenceList);
const commonList = brands1.filter(brand => brands2.includes(brand));
console.log('common list:', commonList);
}
If condition is not met (like if you put 'Mercedes' in brands2) then 'intersectionEvery' won't be satisfied - will be bool false.
If condition is met it will log ["Ford", "VW"] as difference and ["Kia", "Audi"] as common list.
Sandbox: https://jsfiddle.net/bqmg14t6/
SOME
let brands1 = ['Ford', 'Kia', 'VW', 'Audi'];
let brands2 = ['Audi', 'Kia', 'Mercedes', 'Land Rover'];
// Find 'some' brand intersection.
// Meaning some elements inside 'brands2' must be also present in 'brands1':
let intersectionSome = brands2.some( brand => brands1.includes(brand) );
if (intersectionSome) {
const differenceList = brands1.filter(brand => !brands2.includes(brand));
console.log('difference list:', differenceList);
const commonList = brands1.filter(brand => brands2.includes(brand));
console.log('common list:', commonList);
}
Here we are looking for some common brands, not necessarily all.
It will log ["Ford", "VW"] as difference and ["Kia", "Audi"] as common brands.
Sandbox: https://jsfiddle.net/zkq9j3Lh/
Personally, I would use the following function:
var arrayContains = function(array, toMatch) {
var arrayAsString = array.toString();
return (arrayAsString.indexOf(','+toMatch+',') >-1);
}
The "toString()" method will always use commas to separate the values. Will only really work with primitive types.
console.log("searching Array: "+finding_array);
console.log("searching in:"+reference_array);
var check_match_counter = 0;
for (var j = finding_array.length - 1; j >= 0; j--)
{
if(reference_array.indexOf(finding_array[j]) > 0)
{
check_match_counter = check_match_counter + 1;
}
}
var match = (check_match_counter > 0) ? true : false;
console.log("Final result:"+match);
Each item of this array is some number:
var items = Array(523,3452,334,31, ...5346);
How to replace some item with a new one?
For example, we want to replace 3452 with 1010, how would we do this?
var index = items.indexOf(3452);
if (index !== -1) {
items[index] = 1010;
}
Also it is recommend you not use the constructor method to initialize your arrays. Instead, use the literal syntax:
var items = [523, 3452, 334, 31, 5346];
You can also use the ~ operator if you are into terse JavaScript and want to shorten the -1 comparison:
var index = items.indexOf(3452);
if (~index) {
items[index] = 1010;
}
Sometimes I even like to write a contains function to abstract this check and make it easier to understand what's going on. What's awesome is this works on arrays and strings both:
var contains = function (haystack, needle) {
return !!~haystack.indexOf(needle);
};
// can be used like so now:
if (contains(items, 3452)) {
// do something else...
}
Starting with ES6/ES2015 for strings, and proposed for ES2016 for arrays, you can more easily determine if a source contains another value:
if (haystack.includes(needle)) {
// do your thing
}
The Array.indexOf() method will replace the first instance. To get every instance use Array.map():
a = a.map(function(item) { return item == 3452 ? 1010 : item; });
Of course, that creates a new array. If you want to do it in place, use Array.forEach():
a.forEach(function(item, i) { if (item == 3452) a[i] = 1010; });
Answer from #gilly3 is great.
Replace object in an array, keeping the array order unchanged
I prefer the following way to update the new updated record into my array of records when I get data from the server. It keeps the order intact and quite straight forward one liner.
users = users.map(u => u.id !== editedUser.id ? u : editedUser);
var users = [
{id: 1, firstname: 'John', lastname: 'Ken'},
{id: 2, firstname: 'Robin', lastname: 'Hood'},
{id: 3, firstname: 'William', lastname: 'Cook'}
];
var editedUser = {id: 2, firstname: 'Michael', lastname: 'Angelo'};
users = users.map(u => u.id !== editedUser.id ? u : editedUser);
console.log('users -> ', users);
My suggested solution would be:
items.splice(1, 1, 1010);
The splice operation will start at index 1, remove 1 item in the array (i.e. 3452), and will replace it with the new item 1010.
Use indexOf to find an element.
var i = items.indexOf(3452);
items[i] = 1010;
First method
Best way in just one line to replace or update item of array
array.splice(array.indexOf(valueToReplace), 1, newValue)
Eg:
let items = ['JS', 'PHP', 'RUBY'];
let replacedItem = items.splice(items.indexOf('RUBY'), 1, 'PYTHON')
console.log(replacedItem) //['RUBY']
console.log(items) //['JS', 'PHP', 'PYTHON']
Second method
An other simple way to do the same operation is :
items[items.indexOf(oldValue)] = newValue
Easily accomplished with a for loop.
for (var i = 0; i < items.length; i++)
if (items[i] == 3452)
items[i] = 1010;
If using a complex object (or even a simple one) and you can use es6, Array.prototype.findIndex is a good one. For the OP's array, they could do,
const index = items.findIndex(x => x === 3452)
items[index] = 1010
For more complex objects, this really shines. For example,
const index =
items.findIndex(
x => x.jerseyNumber === 9 && x.school === 'Ohio State'
)
items[index].lastName = 'Utah'
items[index].firstName = 'Johnny'
You can edit any number of the list using indexes
for example :
items[0] = 5;
items[5] = 100;
ES6 way:
const items = Array(523, 3452, 334, 31, ...5346);
We wanna replace 3452 with 1010, solution:
const newItems = items.map(item => item === 3452 ? 1010 : item);
Surely, the question is for many years ago and for now I just prefer to use immutable solution, definitely, it is awesome for ReactJS.
For frequent usage I offer below function:
const itemReplacer = (array, oldItem, newItem) =>
array.map(item => item === oldItem ? newItem : item);
A functional approach to replacing an element of an array in javascript:
const replace = (array, index, ...items) => [...array.slice(0, index), ...items, ...array.slice(index + 1)];
The immutable way to replace the element in the list using ES6 spread operators and .slice method.
const arr = ['fir', 'next', 'third'], item = 'next'
const nextArr = [
...arr.slice(0, arr.indexOf(item)),
'second',
...arr.slice(arr.indexOf(item) + 1)
]
Verify that works
console.log(arr) // [ 'fir', 'next', 'third' ]
console.log(nextArr) // ['fir', 'second', 'third']
Replacement can be done in one line:
var items = Array(523, 3452, 334, 31, 5346);
items[items.map((e, i) => [i, e]).filter(e => e[1] == 3452)[0][0]] = 1010
console.log(items);
Or create a function to reuse:
Array.prototype.replace = function(t, v) {
if (this.indexOf(t)!= -1)
this[this.map((e, i) => [i, e]).filter(e => e[1] == t)[0][0]] = v;
};
//Check
var items = Array(523, 3452, 334, 31, 5346);
items.replace(3452, 1010);
console.log(items);
var items = Array(523,3452,334,31,5346);
If you know the value then use,
items[items.indexOf(334)] = 1010;
If you want to know that value is present or not, then use,
var point = items.indexOf(334);
if (point !== -1) {
items[point] = 1010;
}
If you know the place (position) then directly use,
items[--position] = 1010;
If you want replace few elements, and you know only starting position only means,
items.splice(2, 1, 1010, 1220);
for more about .splice
The easiest way is to use some libraries like underscorejs and map method.
var items = Array(523,3452,334,31,...5346);
_.map(items, function(num) {
return (num == 3452) ? 1010 : num;
});
=> [523, 1010, 334, 31, ...5346]
If you want a simple sugar sintax oneliner you can just:
(elements = elements.filter(element => element.id !== updatedElement.id)).push(updatedElement);
Like:
let elements = [ { id: 1, name: 'element one' }, { id: 2, name: 'element two'} ];
const updatedElement = { id: 1, name: 'updated element one' };
If you don't have id you could stringify the element like:
(elements = elements.filter(element => JSON.stringify(element) !== JSON.stringify(updatedElement))).push(updatedElement);
var index = Array.indexOf(Array value);
if (index > -1) {
Array.splice(index, 1);
}
from here you can delete a particular value from array and based on the same index
you can insert value in array .
Array.splice(index, 0, Array value);
Well if anyone is interresting on how to replace an object from its index in an array, here's a solution.
Find the index of the object by its id:
const index = items.map(item => item.id).indexOf(objectId)
Replace the object using Object.assign() method:
Object.assign(items[index], newValue)
items[items.indexOf(3452)] = 1010
great for simple swaps. try the snippet below
const items = Array(523, 3452, 334, 31, 5346);
console.log(items)
items[items.indexOf(3452)] = 1010
console.log(items)
Here is the basic answer made into a reusable function:
function arrayFindReplace(array, findValue, replaceValue){
while(array.indexOf(findValue) !== -1){
let index = array.indexOf(findValue);
array[index] = replaceValue;
}
}
Here's a one liner. It assumes the item will be in the array.
var items = [523, 3452, 334, 31, 5346]
var replace = (arr, oldVal, newVal) => (arr[arr.indexOf(oldVal)] = newVal, arr)
console.log(replace(items, 3452, 1010))
const items = Array(1, 2, 3, 4, 5);
console.log(items)
items[items.indexOf(2)] = 1010
console.log(items)
First, rewrite your array like this:
var items = [523,3452,334,31,...5346];
Next, access the element in the array through its index number. The formula to determine the index number is: n-1
To replace the first item (n=1) in the array, write:
items[0] = Enter Your New Number;
In your example, the number 3452 is in the second position (n=2). So the formula to determine the index number is 2-1 = 1. So write the following code to replace 3452 with 1010:
items[1] = 1010;
I solved this problem using for loops and iterating through the original array and adding the positions of the matching arreas to another array and then looping through that array and changing it in the original array then return it, I used and arrow function but a regular function would work too.
var replace = (arr, replaceThis, WithThis) => {
if (!Array.isArray(arr)) throw new RangeError("Error");
var itemSpots = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] == replaceThis) itemSpots.push(i);
}
for (var i = 0; i < itemSpots.length; i++) {
arr[itemSpots[i]] = WithThis;
}
return arr;
};
presentPrompt(id,productqty) {
let alert = this.forgotCtrl.create({
title: 'Test',
inputs: [
{
name: 'pickqty',
placeholder: 'pick quantity'
},
{
name: 'state',
value: 'verified',
disabled:true,
placeholder: 'state',
}
],
buttons: [
{
text: 'Ok',
role: 'cancel',
handler: data => {
console.log('dataaaaname',data.pickqty);
console.log('dataaaapwd',data.state);
for (var i = 0; i < this.cottonLists.length; i++){
if (this.cottonLists[i].id == id){
this.cottonLists[i].real_stock = data.pickqty;
}
}
for (var i = 0; i < this.cottonLists.length; i++){
if (this.cottonLists[i].id == id){
this.cottonLists[i].state = 'verified';
}
}
//Log object to console again.
console.log("After update: ", this.cottonLists)
console.log('Ok clicked');
}
},
]
});
alert.present();
}
As per your requirement you can change fields and array names.
thats all. Enjoy your coding.
The easiest way is this.
var items = Array(523,3452,334,31, 5346);
var replaceWhat = 3452, replaceWith = 1010;
if ( ( i = items.indexOf(replaceWhat) ) >=0 ) items.splice(i, 1, replaceWith);
console.log(items);
>>> (5) [523, 1010, 334, 31, 5346]
When your array have many old item to replace new item, you can use this way:
function replaceArray(array, oldItem, newItem) {
for (let i = 0; i < array.length; i++) {
const index = array.indexOf(oldItem);
if (~index) {
array[index] = newItem;
}
}
return array
}
console.log(replaceArray([1, 2, 3, 2, 2, 8, 1, 9], 2, 5));
console.log(replaceArray([1, 2, 3, 2, 2, 8, 1, 9], 2, "Hi"));
let items = Array(523,3452,334,31, 5346);
items[0]=1010;
This will do the job
Array.prototype.replace = function(a, b) {
return this.map(item => item == a ? b : item)
}
Usage:
let items = ['hi', 'hi', 'hello', 'hi', 'hello', 'hello', 'hi']
console.log(items.replace('hello', 'hi'))
Output:
['hi', 'hi', 'hi', 'hi', 'hi', 'hi', 'hi']
The nice thing is, that EVERY array will have .replace() property.