I'm using a filter function to find JSON objects in an array called arrayList
, which contains for example:
[
{
"name": "Markdown",
"extension": "(.md)"
},
{
"name": "MultiMarkdown",
"extension": "(.mmd, .txt)"
}
]
I'm using the following code to search on the name
field and find a match for an object with a certain name:
findFormat = (name) => {
let format = arrayList.filter(function (el) {
let pattern = new RegExp(name);
return el.name.match(pattern);
});
return format.name
}
So if I'm searching for an object that has the name "Markdown" then this string gets passed via the name
parameter in the function above, and the RegExp
expression resolves to /Markdown/
.
For the filter function itself, I've implemented the polyfill described at the bottom of the MDN documentation:
if (!Array.prototype.filter)
Array.prototype.filter = function(func, thisArg) {
'use strict';
if ( ! ((typeof func === 'Function') && this) )
throw new TypeError();
var len = this.length >>> 0,
res = new Array(len), // preallocate array
c = 0, i = -1;
if (thisArg === undefined)
while (++i !== len)
// checks to see if the key was set
if (i in this)
if (func(t[i], i, t))
res[c++] = t[i];
else
while (++i !== len)
// checks to see if the key was set
if (i in this)
if (func.call(thisArg, t[i], i, t))
res[c++] = t[i];
res.length = c; // shrink down array to proper size
return res;
};
For the regular expression I'm not using any special flags like i
because I want to find an exact match for "Markdown". However it keeps returning instead MultiMarkdown
. I had thought that the filter function above found only exact matches, and not substrings.
Question: is there a way I can filter for only exact matches, using the filter
and match
methods? Wouldn't the polyfill above return an exact match?
I'm using a filter function to find JSON objects in an array called arrayList
, which contains for example:
[
{
"name": "Markdown",
"extension": "(.md)"
},
{
"name": "MultiMarkdown",
"extension": "(.mmd, .txt)"
}
]
I'm using the following code to search on the name
field and find a match for an object with a certain name:
findFormat = (name) => {
let format = arrayList.filter(function (el) {
let pattern = new RegExp(name);
return el.name.match(pattern);
});
return format.name
}
So if I'm searching for an object that has the name "Markdown" then this string gets passed via the name
parameter in the function above, and the RegExp
expression resolves to /Markdown/
.
For the filter function itself, I've implemented the polyfill described at the bottom of the MDN documentation:
if (!Array.prototype.filter)
Array.prototype.filter = function(func, thisArg) {
'use strict';
if ( ! ((typeof func === 'Function') && this) )
throw new TypeError();
var len = this.length >>> 0,
res = new Array(len), // preallocate array
c = 0, i = -1;
if (thisArg === undefined)
while (++i !== len)
// checks to see if the key was set
if (i in this)
if (func(t[i], i, t))
res[c++] = t[i];
else
while (++i !== len)
// checks to see if the key was set
if (i in this)
if (func.call(thisArg, t[i], i, t))
res[c++] = t[i];
res.length = c; // shrink down array to proper size
return res;
};
For the regular expression I'm not using any special flags like i
because I want to find an exact match for "Markdown". However it keeps returning instead MultiMarkdown
. I had thought that the filter function above found only exact matches, and not substrings.
Question: is there a way I can filter for only exact matches, using the filter
and match
methods? Wouldn't the polyfill above return an exact match?
- 1 There's no such thing as a "JSON object". JSON is a string format. – Scott Marcus Commented Nov 5, 2017 at 19:43
-
You should review what
.match
actually does. – melpomene Commented Nov 5, 2017 at 19:49 - @ScottMarcus w3schools./js/js_json_objects.asp – orlando21 Commented Nov 6, 2017 at 6:42
3 Answers
Reset to default 8There's a few misunderstandings you have:
- Regular expressions is used for matching strings that match a certain pattern. It's a powerful thing but I'd say it's not the best tool to use if you're trying to find an exact match. In that case, you could just use the strict equality operator
===
. (If you did want to use regex, you could add the^
and the$
before the regex to match the first and last characters of the line e.g./^Markdown$/
would only matchMarkdown
) - Polyfills implement missing features of the Javascript standard (EcmaScript) and
Array.prototype.filter
is implemented in all major browsers do you don't need to implement it.
See the example below on how to match name
strictly.
const array = [{
"name": "Markdown",
"extension": "(.md)"
},
{
"name": "MultiMarkdown",
"extension": "(.mmd, .txt)"
}
]
const criteria = 'Markdown';
const result = array.filter(item => item.name === criteria);
console.log('result', result);
You don't need RegEx here and probably shouldn't use it as it will be slower. However, that is not the issue. The issue is that new RegExp(name);
will create a RegEx that does a contains search. See https://developer.mozilla/en-US/docs/Web/JavaScript/Guide/Regular_Expressions.
I would remend changing
let pattern = new RegExp(name);
return el.name.match(pattern);
to
return el.name === name;
Check for equality if you want exact match
let format = arrayList.filter(function (el) {
return el.name === name;
});
Or if you want case insensitive then normalize the cases:
let format = arrayList.filter(function (el) {
return el.name.toLowerCase() === name.toLowerCase();
});