Partial string matching in javascript - javascript

I have this javascript function:
var y;
y = ['ab', 'f', 'c'].indexOf('b')
This returns -1 because b is not a full match against ab
In javascript, what is the easiest way of looking for a partial match.
So I want :
y = ['ab', 'f', 'c'].indexOf('b')
to return 0(index of first element because it found a partial match while comparing b to ab
I understand i cannot do it using indexOf, what is the best way to do it?

You will have to loop through the Array:
var arr = ['ab', 'f', 'c']
function find(a, c) {
for(var i = 0; i < a.length; ++i) {
if(a[i].indexOf(c) != -1)
return i
}
return -1
}
// Example:
document.body.innerHTML = find(arr, "b")

With ES6 Array.prototype.findIndex and arrow functions:
y = ['ab', 'f', 'c'];
y.findIndex(el => el.indexOf('b') > -1); //0

You have multiple way, you can use the method Array.prototype.filter:
var testRegex = /b/;
var result = ['ab','f','c'].map(function(item, index) {
return testRegex.test(item) ? index : null; //return index in the array if found.
}).filter(function(index) {
return index !== null; // filter the result and remove all results that are null;
});
result should equal [0];
if you try with an array like this:
['ab', 'cgt', 'abcd', 'cd', 'efb'];
It should return:
[0, 2, 4]

Related

How can I remove elements with even no of re-occurrence in an array with javascript?

var ar = ['a','a','a','b','e','e']
var charMap ={}
for(let char of ar){
charMap[char] = charMap[char] +1 || 1
}
const result = [];
for(let ch in charMap){
if(charMap[ch] %2 !== 0 ){
result.push(Object.keys(ch))
}
}
console.log(result);
The result should be like ['a','a','a','b'], but I am getting something else.
Please help me out.
Just use filter method by passing a callback provided function as argument.
var ar = ['a','a','a','b','e','e']
ar = ar.filter(function(item){
return ar.filter(elem => elem == item).length %2 == 1;
});
console.log(ar);
Another approach is to use filter method in combination with reduce.
var ar = ['a','a','a','b','e','e']
ar = ar.filter(function(item){
return ar.reduce((pre, current) => (current == item) ? ++pre : pre, 0) % 2 == 1;
});
console.log(ar);
You could take a Map and count the values in advance. Then filter the array by checking the count.
var array = ['a', 'a', 'a', 'b', 'e', 'e'],
result = array.filter(
Map.prototype.get,
array.reduce((m, v) => m.set(v, (m.get(v) || 2) - 1), new Map)
);
console.log(result);

why is this removeDuplicate not working?

I making a function that simply removes duplicate strings, so there are only unique strings left:
var d = ['a','b','B','C','d','e','f','e'];
d.length; //8
function removeDuplicates(data) {
var i, j, a, b;
for(i = 0; i < data.length - 1; i++) {
a = data[i];
for(j = i; j < data.length; j++) {
b = data[j];
if (a.toLowerCase() == b.toLowerCase()) {
data.splice(j, 1);
}
}
}
}
removeDuplicates(d)
d.length; //4 ????
There were only two duplicates, Only B, e should have gotten removed.
but I get this:
["b", "C", "e", "e"]
Your issue is coming from the fact that any time i === j you'll have a match, and it'll be removed. In your inner loop, just put a check so that you only do your "remove them if they're equal" in situations where i !== j
Also, as nnn noted in the comments, splicing will mess up the index. The cleanest way to do this is with a filter and an every.
Updated solution below:
var d = ['a', 'b', 'B', 'C', 'd', 'e', 'f', 'e'];
var e = ['e','e','e','e'];
// d.length; //8
function removeDuplicates(data) {
const noDuplicates = data.filter((letter, ogIndex) => {
return data.every((innerLetter, innerIndex) => {
if (ogIndex < innerIndex) {
const check = letter.toLowerCase() !== innerLetter.toLowerCase();
return check;
} else {
return true;
}
})
})
return noDuplicates
}
console.log(removeDuplicates(d));
// ["a", "B", "C", "d", "f", "e"]
console.log(removeDuplicates(e));
// ["e"]
With ES6/ES2015, a simple way of getting a list of unique items is to use the new Set data type.
To "unique"-ify an array, just convert it to a set and then back to an array. i.e.
[...new Set(originalArray)]
(Update: My answer originally used Array.from(S_E_T) to convert the set back to an array. I have now changed it to [...S_E_T] to do that conversion.)
To do the same in a case-insensitive manner, follow the same logic, but just convert each original array element to its lowercase equivalent before converting that whole array to the set.
To do keep only the first instance of a string of any case (e.g. to keep 'cAt' from ['cAt', 'CaT'] instead of just the all-lowercased 'cat'), first perform the case-insensitive search as above, then get the index of each unique lowercase element from the lowercased un-uniqified original array, then use that index to retrieve the whichever-cased element from the original-cased un-uniqified original array.
const show = msg => {console.log(JSON.stringify(msg))};
const f = (arr) => {
const arrLC = arr.map(x => x.toLowerCase(x));
return [...new Set(arrLC)].map(x => arr[arrLC.indexOf(x)])
};
const d1 = ['a','b','B','C','d','e','f','e'];
const d2 = ['e', 'e', 'e', 'e', 'e'];
show(d1);
show([...new Set(d1)]);
show([...new Set(d1.map(x => x.toLowerCase(x)))]);
show(f(d1));
show('------');
show(d2);
show([...new Set(d2)]);

Reverse part of an array using javaScript

I have an array in Javascript like so:
var v = new Array("a","b","c","d","e","f"...);
I would like to reverse it but keep the first two elements, so it would turn into:
"a","b",...."f","e","d","c"
How can I do this?
Try this way:
var v = new Array("a","b","c","d","e","f");
var newArr = v.splice(0,2).concat(v.reverse()); // get the first 2 out of the array
console.log(newArr);
splice
concat
reverse
v = [].concat( v.slice(0,2), v.slice(2).reverse());
//v --> ["a", "b", "f", "e", "d", "c"]
function reverseArrayFromThirdElement(array, copy) {
var arrayCopy = copy ? array.concat() : array;
return [array[0], array[1]].concat(
(arrayCopy.splice(0, 2), arrayCopy.reverse())
);
}
It allows you to choose if you want to keep your array safe from slicing. Pass copy as true if you want your array to be internally copied.
It works like Array.Reverse from C#:
const arrayReverse = (arr, index, length) => {
let temp = arr.slice(index, index + length);
temp.reverse();
for (let i = 0, j = index; i < temp.length, j < index + length; i++, j++) {
arr[j] = temp[i];
}
return arr;
};
Example:
let test = ['a', 'b', 'c', 'd', 'e', 'f'];
test = arrayReverse(test, 4, 2);
console.log(test); // returns [ 'a', 'b', 'c', 'd', 'f', 'e' ]
For inplace reversal, this can be done using splice method:
let alp = new Array("a","b","c","d","e","f");
alp.splice(2,4,...alp.slice(2).reverse());
console.log(alp);
Use destructuring:
const reversedEnd = [...v.slice(0, 2), ...v.slice(2).reverse()];
const reversedBeginning = [...v.slice(0, 2).reverse(), ...v.slice(2)];
const reversedMiddle = [...v.slice(0, 2), ...v.slice(2,4).reverse(), ...v.slice(4)];

Check if all values of array are equal

I need to find arrays where all values are equal. What's the fastest way to do this? Should I loop through it and just compare values?
['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
const allEqual = arr => arr.every( v => v === arr[0] )
allEqual( [1,1,1,1] ) // true
Or one-liner:
[1,1,1,1].every( (val, i, arr) => val === arr[0] ) // true
Array.prototype.every (from MDN) :
The every() method tests whether all elements in the array pass the test implemented by the provided function.
Edit: Be a Red ninja:
!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Results:
var array = ["a", "a", "a"] => result: "true"
var array = ["a", "b", "a"] => result: "false"
var array = ["false", ""] => result: "false"
var array = ["false", false] => result: "false"
var array = ["false", "false"] => result: "true"
var array = [NaN, NaN] => result: "false"
Warning:
var array = [] => result: TypeError thrown
This is because we do not pass an initialValue. So, you may wish to check array.length first.
You can turn the Array into a Set. If the size of the Set is equal to 1, then all elements of the Array are equal.
function allEqual(arr) {
return new Set(arr).size == 1;
}
allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
This works. You create a method on Array by using prototype.
if (Array.prototype.allValuesSame === undefined) {
Array.prototype.allValuesSame = function() {
for (let i = 1; i < this.length; i++) {
if (this[i] !== this[0]) {
return false;
}
}
return true;
}
}
Call this in this way:
let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame(); // false
In JavaScript 1.6, you can use Array.every:
function AllTheSame(array) {
var first = array[0];
return array.every(function(element) {
return element === first;
});
}
You probably need some sanity checks, e.g. when the array has no elements. (Also, this won't work when all elements are NaN since NaN !== NaN, but that shouldn't be an issue... right?)
And for performance comparison I also did a benchmark:
function allAreEqual(array){
if(!array.length) return true;
// I also made sure it works with [false, false] array
return array.reduce(function(a, b){return (a === b)?a:(!b);}) === array[0];
}
function same(a) {
if (!a.length) return true;
return !a.filter(function (e) {
return e !== a[0];
}).length;
}
function allTheSame(array) {
var first = array[0];
return array.every(function(element) {
return element === first;
});
}
function useSome(array){
return !array.some(function(value, index, array){
return value !== array[0];
});
}
Results:
allAreEqual x 47,565 ops/sec ±0.16% (100 runs sampled)
same x 42,529 ops/sec ±1.74% (92 runs sampled)
allTheSame x 66,437 ops/sec ±0.45% (102 runs sampled)
useSome x 70,102 ops/sec ±0.27% (100 runs sampled)
So apparently using builtin array.some() is the fastest method of the ones sampled.
update 2022 version: use Set()
let a = ['a', 'a', 'b', 'a'];
let b = ['a', 'a', 'a', 'a'];
const check = (list) => {
const setItem = new Set(list);
return setItem.size <= 1;
}
const checkShort = (list) => (new Set(list)).size <= 1
check(a); // false;
check(b); // true;
checkShort(a); // false
checkShort(b); // true
Update new solution: check index
let a = ['a', 'a', 'b', 'a'];
let b = ['a', 'a', 'a', 'a'];
let check = (list) => list.every(item => list.indexOf(item) === 0);
check(a); // false;
check(b); // true;
Updated with ES6:
Use list.every is the fastest way:
let a = ['a', 'a', 'b', 'a'];
let check = (list) => list.every(item => item === list[0]);
old version:
var listTrue = ['a', 'a', 'a', 'a'];
var listFalse = ['a', 'a', 'a', 'ab'];
function areWeTheSame(list) {
var sample = list[0];
return (list.every((item) => item === sample));
}
If you're already using underscore.js, then here's another option using _.uniq:
function allEqual(arr) {
return _.uniq(arr).length === 1;
}
_.uniq returns a duplicate-free version of the array. If all the values are the same, then the length will be 1.
As mentioned in the comments, given that you may expect an empty array to return true, then you should also check for that case:
function allEqual(arr) {
return arr.length === 0 || _.uniq(arr).length === 1;
}
Shortest answer using underscore/lodash
function elementsEqual(arr) {
return !_.without(arr, arr[0]).length
}
spec:
elementsEqual(null) // throws error
elementsEqual([]) // true
elementsEqual({}) // true
elementsEqual([1]) // true
elementsEqual([1,2]) // false
elementsEqual(NaN) // true
edit:
Or even shorter, inspired by Tom's answer:
function elementsEqual2(arr) {
return _.uniq(arr).length <= 1;
}
spec:
elementsEqual2(null) // true (beware, it's different than above)
elementsEqual2([]) // true
elementsEqual2({}) // true
elementsEqual2([1]) // true
elementsEqual2([1,2]) // false
elementsEqual2(NaN) // true
every() function check if all elements of an array
const checkArr = a => a.every( val => val === a[0] )
checkArr(['a','a','a']) // true
You can use Array.every if supported:
var equals = array.every(function(value, index, array){
return value === array[0];
});
Alternatives approach of a loop could be something like sort
var temp = array.slice(0).sort();
var equals = temp[0] === temp[temp.length - 1];
Or, if the items are like the question, something dirty like:
var equals = array.join('').split(array[0]).join('').length === 0;
Also works.
Yes, you can check it also using filter as below, very simple, checking every values are the same as the first one:
//ES6
function sameValues(arr) {
return arr.filter((v,i,a)=>v===a[0]).length === arr.length;
}
also can be done using every method on the array:
//ES6
function sameValues(arr) {
return arr.every((v,i,a)=>v===a[0]);
}
and you can check your arrays like below:
sameValues(['a', 'a', 'a', 'a']); // true
sameValues(['a', 'a', 'b', 'a']); // false
Or you can add it to native Array functionalities in JavaScript if you reuse it a lot:
//ES6
Array.prototype.sameValues = Array.prototype.sameValues || function(){
this.every((v,i,a)=>v===a[0]);
}
and you can check your arrays like below:
['a', 'a', 'a', 'a'].sameValues(); // true
['a', 'a', 'b', 'a'].sameValues(); // false
You can get this one-liner to do what you want using Array.prototype.every, Object.is, and ES6 arrow functions:
const all = arr => arr.every(x => Object.is(arr[0], x));
Now you can make use of sets to do that easily.
let a= ['a', 'a', 'a', 'a']; // true
let b =['a', 'a', 'b', 'a'];// false
console.log(new Set(a).size === 1);
console.log(new Set(b).size === 1);
I think the simplest way to do this is to create a loop to compare the each value to the next. As long as there is a break in the "chain" then it would return false. If the first is equal to the second, the second equal to the third and so on, then we can conclude that all elements of the array are equal to each other.
given an array data[], then you can use:
for(x=0;x<data.length - 1;x++){
if (data[x] != data[x+1]){
isEqual = false;
}
}
alert("All elements are equal is " + isEqual);
You can convert array to a Set and check its size
In case of primitive array entries, i.e. number, string:
const isArrayWithEqualEntries = array => new Set(array).size === 1
In case of array of objects with some field to be tested for equivalence, say id:
const mapper = ({id}) => id
const isArrayWithEqualEntries = array => new Set(array.map(mapper)).size === 1
You can use this:
function same(a) {
if (!a.length) return true;
return !a.filter(function (e) {
return e !== a[0];
}).length;
}
The function first checks whether the array is empty. If it is it's values are equals..
Otherwise it filter the array and takes all elements which are different from the first one. If there are no such values => the array contains only equal elements otherwise it doesn't.
arr.length && arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0];
Its Simple.
Create a function and pass a parameter.
In that function copy the first index into a new variable.
Then Create a for loop and loop through the array.
Inside a loop create an while loop with a condition checking whether the new created variable is equal to all the elements in the loop.
if its equal return true after the for loop completes else return false inside the while loop.
function isUniform(arra){
var k=arra[0];
for (var i = 0; i < arra.length; i++) {
while(k!==arra[i]){
return false;
}
}
return true;
}
The accepted answer worked great but I wanted to add a tiny bit. It didn't work for me to use === because I was comparing arrays of arrays of objects, however throughout my app I've been using the fast-deep-equal package which I highly recommend. With that, my code looks like this:
let areAllEqual = arrs.every((val, i, arr) => equal(val, arr[0]) );
and my data looks like this:
[
[
{
"ID": 28,
"AuthorID": 121,
"VisitTypeID": 2
},
{
"ID": 115,
"AuthorID": 121,
"VisitTypeID": 1
},
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
],
[
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
],
[
{
"ID": 5,
"AuthorID": 121,
"VisitTypeID": 1
},
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
]
]
You could use a for loop:
function isEqual(arr) {
var first = arr[0];
for (let i = 1; i < arr.length; i++) {
if (first !== arr[i]) {
return false;
}
}
return true;
}
Underscore's _.isEqual(object, other) function seems to work well for arrays. The order of items in the array matter when it checks for equality. See http://underscorejs.org/#isEqual.
var listTrue = ['a', 'a', 'a', 'a'];
var listFalse = ['a', 'a', 'a', 'ab'];
function areWeTheSame(list) {
var sample = list[0];
return !(list.some(function(item) {
return !(item == sample);
}));
}
function isUniform(array) {
for (var i=1; i< array.length; i++) {
if (array[i] !== array[0]) { return false; }
}
for (var i=1; i< array.length; i++) {
if (array[i] === array[0]) { return true; }
}
}
For the first loop; whenever it detects uneven, returns "false"
The first loop runs, and if it returns false, we have "false"
When it's not return false, it means there will be true, so we do the second loop. And of course we will have "true" from the second loop (because the first loop found it's NOT false)
Create a string by joining the array.
Create string by repetition of the first character of the given array
match both strings
function checkArray(array){
return array.join("") == array[0].repeat(array.length);
}
console.log('array: [a,a,a,a]: ' + checkArray(['a', 'a', 'a', 'a']));
console.log('array: [a,a,b,a]: ' + checkArray(['a', 'a', 'b', 'a']));
And you are DONE !
Another interesting way when you use ES6 arrow function syntax:
x = ['a', 'a', 'a', 'a']
!x.filter(e=>e!==x[0])[0] // true
x = ['a', 'a', 'b', 'a']
!x.filter(e=>e!==x[0])[0] // false
x = []
!x.filter(e=>e!==x[0])[0] // true
And when you don't want to reuse the variable for array (x):
!['a', 'a', 'a', 'a'].filter((e,i,a)=>e!==a[0])[0] // true
IMO previous poster who used array.every(...) has the cleanest solution.
this might work , you can use the comment out code as well that also woks well with the given scenerio.
function isUniform(){
var arrayToMatch = [1,1,1,1,1];
var temp = arrayToMatch[0];
console.log(temp);
/* return arrayToMatch.every(function(check){
return check == temp;
});*/
var bool;
arrayToMatch.forEach(function(check){
bool=(check == temp);
})
console.log(bool);
}
isUniform();
Use index of operator for every item of array
to check if it exists or not. If even one item returns -1 (doesn't exist then it will be false)
nst arr1 = [1, 3, 5];
const arr2 = [5, 7, 9];
const arr3 = [1, 3, 5];
arr1.every(item => arr2.indexOf(item) != -1)
// this will return false
arr1.every(item => arr3.indexOf(item) != -1)
// this will return true
Simple one line solution, just compare it to an array filled with the first entry.
if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))
**// Logical Solution:- Declare global array and one variable(To check the condition) whether all element of an array contains same value or not.**
var arr =[];
var isMatching = false;
for(var i=0;i<arr.length;i++){
if(String(arr[i]).toLowerCase()== "Your string to check"){
isMatching=true;
// Array has same value in all index of an array
}
else{
isMatching=false;
// Array Doesn't has same value in all index of an array
break;
}
}
// **Check isMatching variable is true or false**
if(isMatching){ // True
//If Array has same value in all index, then this block will get executed
}
else{ //False
//If Array doesn't has same value in all index, then this block will get executed
}

Deleting from an array based on a string value

I have defined an array like so :
var myArray = {myNewArray: ['string1' , 'string2' , 'string3']};
I want to iterate over the array and delete an element that matches a particular string value. Is there a clean way in jQuery/javascript to achieve this ?
Or do I need to iterate over each element, check its value and if its value matches the string im comparing, get its id and then use that id to delete from the array ?
Here's a JSFiddle showing your solution
var strings = ['a', 'b', 'c', 'd'];
document.write('initial data: ' + strings);
var index = 0;
var badData = 'c';
for(index = 0; index < strings.length; index++)
{
if(strings[index] == badData)
{
strings.splice(index, 1);
}
}
document.write('<br>final data: '+ strings);​
JavaScript arrays have an indexOf method that can be used to find an element, then splice can be used to remove it. For example:
var myNewArray = ['A', 'B', 'C'];
var toBeRemoved = 'B';
var indexOfItemToRemove = myNewArray.indexOf(toBeRemoved);
if (indexOfItemToRemove >= 0) {
myNewArray.splice(indexOfItemToRemove, 1);
}
After that code executes, myNewArray is ['A', 'C'].
You can use Array.filter.
filteredArray = myArray.myNewArray.filter(function(el){
return el === "string";
});
You can check compatibility at Kangax's compat tables.
You could filter the array using $.grep
var myArray = {myNewArray: ['string1' , 'string2' , 'string3']};
myArray = { myNewArray: $.grep(myArray.myNewArray,function(val){
return val !== "string1";
})};
//console.log(myArray);
my newARR = oldArr.splice( $.inArray( removeItem , oldArr ) , 'deleteThisString');

Categories