javascript: match string to array elements - javascript

I have a set of values (groups) in a comma delimited string and would like to check if any of those values match any array items (reqRights) and return true or false, but is returns undefined error.
const reqRights = ["18900253","3217840","1053"];
const groups = "3217635,18272308,1053,3217633,18900253,3217698,3217699,3217840,10162510";
function checker(value) {
var groups = groups.split(",");
console.log(groups);
return groups.every(function(v) {
return value.indexOf(v) !== -1;
});
}
arr = reqRights.filter(checker);
console.log(arr);
js engine SpiderMonkey 1.8, does not support .includes and some methods

You're using const on groups, so you cannot reassign it. And you also should move groups.split(",") outside of checker function to avoid creating a new array every time calling checker.
some can help you to check regRights item is in groups instead of every.
const reqRights = ["18900253","3217840","1053"];
const groups = "3217635,18272308,1053,3217633,18900253,3217698,3217699,3217840,10162510";
const groupsArray = groups.split(",");
function checkGroupValue(group) {
return group === value;
}
function checker(value) {
return groupsArray.some(checkGroupValue);
}
arr = reqRights.filter(checker);
console.log(arr);

const reqRights = ["18900253","3217840","1053"];
const groupsConstant = "3217635,18272308,1053,3217633,18900253,3217698,3217699,3217840,10162510";
function checker(value) {
var groups = groupsConstant.split(",");
return groups.every(v => groups.indexOf(v) !== -1);
}
arr = reqRights.filter(checker);
console.log('elements matched: ', arr.length ? 'yes' : 'no');

I was trying to avoid the indexOf as it might give a false positive result (example: reqRight "1053" would be listed if found in "1053568")
THis is not necessarily the shortest way, but should be compatible with spiderMonkey 1.8
const reqRights = ["18900253","3217840","1053"];
const groups = "3217635,18272308,1053,3217633,18900253,3217698,3217699,3217840,10162510";
function checker(values, required) {
var valuesArray = values.split(",");
return valuesArray.filter((value) => {
return required.filter((req) => {
return req === value;
}).length > 0;
})
}
arr = checker(groups, reqRights);
console.log(arr);

Use Array.find in filtering from groups:
const reqRights = ["18900253","3217840","1053"];
const groups = "3217635,18272308,1053,3217633,18900253,3217698,3217699,3217840,10162510";
const checker = value =>
({[value]: reqRights.find(v => value === v) ? true : false});
const checked = groups.split(`,`).map(checker);
console.log(checked);
Or maybe concat both (groups as array) arrays, sort that numerically and filter the result on double values.
const reqRights = ["18900253","3217840","1053"];
const groups = "3217635,18272308,1053,3217633,18900253,3217698,3217699,3217840,10162510";
const checked = groups.split(`,`)
.concat(reqRights)
.sort( (a, b) => +a - +b)
.filter((v, i, self) => self[i+1] === v);
console.log(checked);

You can simply achieve this by using Array.map() along with Array.some() method.
Live Demo :
const reqRights = ["18900253","3217840","1053"];
const groups = "3217635,18272308,1053,3217633,18900253,3217698,3217699,3217840,10162510";
const res = groups.split(',').map(item => {
return reqRights.some(n => item === n)
});
console.log(res);

Related

A number which has same frequency of all integers present

I want to check if all the integers present in a number has the same frequency.
Sample Input :
1212
Sample Output :
True
I am able to get the frequency using reduce function . But not able to compare the values.
let countOccurrences = arr => arr.reduce((accm,x)=> (accm[x] = ++accm[x] || 1,accm),{});
var obj = (countOccurrences([2,3,4,2,3,4]))
for(var i in obj)
console.log(obj[i+1]);
if(obj[i]===obj[i+1]){
console.log("true");
}else{
console.log("false");
}
//end-here
});
One way would be to use the Array every() method to check that every value in your object is equal to the first one (after converting to an array of values).
const countOccurrences = arr => arr.reduce((accm,x)=> (accm[x] = ++accm[x] || 1,accm),{});
const obj = countOccurrences([2,3,4,2,3,4]);
const same = Object.values(obj).every((el, _, arr) => el === arr[0]);
console.log(same);
You can use Set to remove dupicates
let countOccurrences = arr => arr.reduce((accm,x)=> (accm[x] = ++accm[x] || 1,accm),{});
var obj = (countOccurrences([2,3,4,2,3,4]));
const isSameFrequency = (new Set(Object.values(obj))).size == 1;
console.log(isSameFrequency);

Delete all occurrence of duplicate values in an array in javascript/jquery

I am trying to work on a problem where I want to remove all the occurrences of similar value in an array
eg.
var sampleArr = ["mary","jane","spiderman","jane","peter"];
and I am trying to get result as => ["marry","spiderman","peter"]
how do I get this?
You can use filter()
var arr = ["mary","jane","spiderman","jane","peter"];
var unique = arr.filter((x, i) => arr.indexOf(x) === i);
console.log(unique);
var sampleArr = ["mary","jane","spiderman","jane","peter"];
var unique = [];
var itemCount = {};
sampleArr.forEach((item,index)=>{
if(!itemCount[item]){
itemCount[item] = 1;
}
else{
itemCount[item]++;
}
});
for(var prop in itemCount){
if(itemCount[prop]==1){
unique.push(prop);
}
}
console.log(unique);
Check this.
You can count the frequency of the character and just pick the character whose frequency is 1.
const arr = ["mary","jane","spiderman","jane","peter"];
frequency = arr.reduce((o,ch) => {
o[ch] = (o[ch] || 0) + 1;
return o;
}, {}),
unique = Object.keys(frequency).reduce((r,k) => frequency[k] === 1? [...r, k]: r, []);
console.log(unique);
You can use filter:
var sampleArr = ["mary","jane","spiderman","jane","peter"];
var result = sampleArr.filter((e,_,s)=>s.filter(o=>o==e).length<2);
// or with reduce and flatmap
const result1 = Object.entries(sampleArr.reduce((a,e)=>(a[e]??=0, a[e]++, a),{})).flatMap(([k,v])=>v==1 ? k: []);
console.log(result)
console.log(result1);
lot of solution, here easy solution to understand using match to have the occurence and filter to eliminate:
var arr = ['ab','pq','mn','ab','mn','ab'];
var st = arr.join(",");
result = arr.filter(it => {
let reg = new RegExp(it, 'g');
return st.match(reg).length == 1;
});
console.log(result);// here ["pq"]
filter seems to be your best bet here if you need extremely robust performance. No real need for jQuery in this instance. Personally, I would opt for readability for something like this and instead sort, set duplicates to null, and then remove all null values.
var sampleArr = ["mary","jane","spiderman","jane","peter"];
var result = sampleArr.sort().forEach((value, index, arr) => {
// if the next one is the same value,
// set this one to null
if(value === arr[value + 1])
return arr[index] = null;
// if the previous one is null, and the next one is different,
// this is the last duplicate in a series, so should be set to null
if(arr[value - 1] === arr[index + 1] !== value)
return arr[index] = null;
return
})
.filter(value => value === null) //remove all null values
console.log(result);

How to filter the matched element at top index in an array in JS

I have a list of array as follows:
var arr = ['Ashwin Rathod','Basker Babu','Cherry Spanish','Dravid Mukund'];
I have a search box and If I search for 'Mukund',then I should show all the results provided the string which contains 'Mukund' should come at top but in my case all the results are coming in alphabetical order(from backend).I did that using array.filter but I want to do it in any other best way.Can anyone please suggest me help.Thanks.
This is what I tried,
function filterResults() {
const matchedJobList = [],
unMatchedJobList = [];
arr.filter(function(job) {
if (job.toUpperCase().includes(mySearchedString.toUpperCase())) {
matchedJobList.push(job);
} else {
unmatchedJobList.push(job);
}
});
return [...matchedJobList, ...unmatchedJobList];
}
result:
['Dravid Mukund','Ashwin Rathod','Basker Babu','Cherry Spanish'];
I got the result as expected but hoping to get the best method to do it.
An alternative could be the function reduce + unshift in order to add the target strings at the first indexes of the array.
let arr = ['Ashwin Rathod','Basker Babu','Cherry Spanish','Dravid Mukund'],
target = 'Mukund',
result = arr.reduce((a, c) => {
if (c.toUpperCase().includes(target.toUpperCase())) a.unshift(c);
else a.push(c);
return a;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you don't mind the potential change of unmatched items order then you can go for sort function:
function filterResults() {
const sorderArray = [...arr];
sorderArray.sort(item => item.toUpperCase().indexOf(mySearchedString.toUpperCase()) !== -1 ? -1 : 1);
return sorderArray;
}
Sort function works directly on the array so I'm creating a copy of the arr to prevent it's mutation.
That is not filtering, that is sorting.
const arr = ['Ashwin Rathod', 'Basker Babu', 'Cherry Spanish', 'Dravid Mukund'];
const mySearchedString = 'Mukund';
function filterResults() {
const clonedResults = [...arr];
return clonedResults.sort((job1, job2) => {
const job1match = job1.toUpperCase().includes(mySearchedString.toUpperCase());
const job2match = job2.toUpperCase().includes(mySearchedString.toUpperCase());
if (job2match && !job1match) return 1;
return 0;
});
}
console.log(filterResults());
We can move founded element to the top:
let arr = ['Ashwin Rathod','Basker Babu','Cherry Spanish','Dravid Mukund'],
search = 'Mukund';
arr.forEach((element, ind) => {
if (element.indexOf(search))
arr.unshift(arr.splice(ind, 1)[0]);
});
console.log(arr);
Using splice()
const arr = ['Ashwin Rathod', 'Basker Babu', 'Cherry Spanish', 'Dravid Mukund']
const search = 'Mukund'
const index = arr.findIndex(e => e.includes(search))
console.log([...arr.splice(index, 1), ...arr]);
You should be using a sort for this, not a filter. Here is an example using a sort method.
const getMatchingLetters = (word, search) => {
return word.toLowerCase().split("").filter(l => {
return search.toLowerCase().includes(l);
})
}
const sortBySearch = (arr, search) => {
return arr.sort((a, b) => {
return getMatchingLetters(a, search).length - getMatchingLetters(b, search).length
}).reverse();
}
const myArray = ['Ashwin Rathod','Basker Babu','Cherry Spanish','Dravid Mukund'];
const searchTerm = "Mukund";
console.log(sortBySearch(myArray, searchTerm));

How to get positon of all words from array depends of includes

I have the Array below and I want to get position of all three values when I type "ca" so it will return me 1,2,3
const withoutAccent = ["xyz", "can", "cant", "cannot"]
let test = withoutAccent.indexOf(withoutAccent.includes("ca"));
console.log(test)
You can use reduce
Loop through array
Check if str is present in current element or not
If present add the current index to final output, else don't
let arr = ["xyz", "can", "cant", "cannot"]
let test = (str) => {
return arr.reduce((op, inp, i) => {
if (inp.includes(str)) {
op.push(i)
}
return op
}, [])
}
console.log(test('ca'))
On side note:- In case you want to achieve case insensitivity
inp.toLowerCase().includes(str.toLowerCase())
You can do it with Array.prototype.map to map to the index of the array if the search query is matched else it will map to null.
The next Array.prototype.filter is applied to filter out the null from the array for unmatched strings, which is then finally joined to a string using Array.prototype.join():
let letters = ["xyz", "can", "cant", "cannot"];
function getIndices(letters, query){
return letters.map((letter, idx) => letter.includes(query) ? idx : null )
.filter(e => e !== null )
.join(", ");
}
console.log(getIndices(letters, "ca"));
letters = ["xyz", "xy", "cant", "cannot"];
console.log(getIndices(letters, "xy"));
You can use reduce and includes.
const withoutAccent = ['xyz', 'can', 'cant', 'cannot'];
const test = withoutAccent.reduce((acc, val, index) => val.includes('ca') ? [...acc, index] : acc,[]);
console.log(test);
You can map to the index using undefined as a placeholder for the entries you don't want, then filter them out:
const result = test.map((entry, index) => entry.includes("ca") && index)
.filter(x => x !== false);
The && means that the intermediate array's entries will either be numbers (indexes) or false (for the ones we don't want); then we filter out the ones that are false. It works because && is curiously-powerful: It evaluates its first operand and, if that's falsy, results in that value; otherwise it evaluates its right-hand operand and results in that value. So if includes returns false, the && result is false. Otherwise, it's the index value.
Live Example:
const test = ["xyz", "can", "cant", "cannot"];
const result = test.map((entry, index) => entry.includes("ca") && index)
.filter(x => x !== false);
console.log(result);
That makes two passes through the array.
Or use a simple loop:
const result = [];
for (const [index, entry] of test.entries()) {
if (entry.includes("ca")) {
result.push(index);
}
}
Live Example:
const test = ["xyz", "can", "cant", "cannot"];
const result = [];
for (const [index, entry] of test.entries()) {
if (entry.includes("ca")) {
result.push(index);
}
}
console.log(result);
Since your question uses ES2015+ features (String.prototype.includes), the examples above use ES2015+ features (const, arrow funtions, Array.prototype.entries, for-of...). You can do this in ES5 and earlier too, though, if you need to:
var result = test.map(function(entry, index) {
return entry.indexOf("ca") !== -1 && index;
})
.filter(function(x) {
return x !== false;
});
and
var result = [];
test.forEach(function(entry, index) {
if (entry.indexOf("ca") !== -1) {
result.push(index);
}
});

List traversal with two adjacent elements in a Functional way

I'm trying to implement functional version of the below code
const adjacent = (list) => {
let results = [];
for (let idx = 0; idx < list.length - 1; idx++) {
const computedRes = someComplexFn(list[idx], list[idx + 1]);
results.push(computedRes );
}
return results;
}
i have come with the following version
const locations = [1,2,3,4,5];
const calcRatioFn = (x, y) => x+y;
const adjacentMap = (list, result=[]) => {
if(R.length(list) < 2) {
return result;
}
const f1 = R.head(list);
const f2 = R.tail(list);
result.push(calcRatioFn(f1 ,R.head(f2)));
return adjacentMap(R.tail(list), result);
}
const results = adjacentMap(locations);
console.log(results);
Are any any other simple solution to the above?
Can we avoid the default result value parameter and if condition check from the above function?
JSBin Link
http://jsbin.com/veyihepulu/1/edit?html,js,console
One approach would be to create a sliding window of adjacent elements using R.aperture. Then for a bit of extra sugar someComplexFn can be wrapped with R.apply to convert the binary function into one that accepts an array of two elements.
Your example would then look something like:
const adjacentMap = R.pipe(R.aperture(2), (R.map(R.apply(someComplexFn))))
Another approach would be to use converge on the array without the last element and the array without the first element.
let locations = [1,2,3,4,5];
const calcRatio = (x, y) => x+y;
// adjacentMap :: Array -> Array
const adjacentMap = R.converge(
R.zipWith(calcRatio),
[ R.init, R.tail]
);
// saveAdjacentMap :: Array -> Array
const saveAdjacentMap = R.cond([
[R.compose(R.lt(1), R.length), adjacentMap ],
[R.T, R.identity]
]);
console.log(saveAdjacentMap(locations));
Your JSBin uses Ramda 0.8.0. Things have changed in the current version 0.24.1.
The following code maybe what you require or can be adapted for your required solution.
const fn = (acc, c, i, a) => {
return !(a[i + 1])
? acc
: acc.concat(c + a[i + 1])
}
const _adjacentMap = (fn, list) => {
return list.reduce(fn, [])
}
const locations = [1,2,3,4,5]
const result = _adjacentMap(fn, locations)
console.log(result)
// => [ 3, 5, 7, 9 ]

Categories

Resources