Lodash / js: Filtering values ​​inside an object based on regular expressions and getting the highest compared

For next json

[ { "index": "xyz", ... }, { "index": "abc1234", ... }, { "index": "xyz", ... }, { "index": "abc5678", ... } ... 

I want to filter abc values ​​and xyz values ​​separately.

I tried the following to get the values

  var x = _.filter(jsonData, function (o) { return /abc/i.test(o.index); }); 

and he worked to give filtered outs.

Now I want to get the highest of abc values, if there are abc123 , abc444 , abc999 , then the code should return abc999 .

I can repeat the loop using lodash, but can this be done with a single call - in the same one that is being filtered out?

+5
source share
7 answers

You can use Array.prototype.reduce() , String.prototype.replace() with RegExp /\D+/ to match and delete characters that are not numbers. Check if the previous part of the line is less than the current line in the line

 var jsonData = [ { "index": "xyz", }, { "index": "abc1234", }, { "index": "xyz", }, { "index": "abc5678", }, { "index": "abc1", }]; var x = jsonData.reduce(function (o, prop) { return /abc/i.test(prop.index) ? !o || +prop.index.replace(/\D+/, "") > +o.replace(/\D+/, "") ? prop.index : o : o }, 0); console.log(x); 
+4
source

If you want to find the maximum value of abc{SOME_NUMBER} and the filter at the same time, you can simply use regular iteration instead of _.filter :

 let jsonData = [{"index": "xyz"},{"index": "abc1234"}, {"index": "xyz"},{"index": "abc5678"}]; let max = Number.MIN_SAFE_INTEGER; // value for the max number at the end of "abc" let item; // item containing the max abc${NUMBER} value let filtered = []; // filtered array containing abc strings jsonData.forEach((curr) => { // filter test if (/abc/i.test(curr.index)) { filtered.push(curr); // max value test const [digits] = curr.index.match(/\d+/); const test = parseInt(digits); if (test > max) { max = test; item = curr; } } }); console.log('Item:\n', item, '\n\n----\nFiltered:\n', filtered); 
+2
source

One way to do this with lodash is to replace filter with maxBy in your code.

Of course, this drawback is that if the collection does not have valid elements, it will arbitrarily return invalid elements. Thus, after receiving the result, an additional verification of reality is necessary.

This is why I highlighted the verification / filtering code in a separate function:

 var jsonData = [{ "index": "xyz", }, { "index": "abc1234", }, { "index": "xyz", }, { "index": "abc5678", }]; var isValid = function(o) { return /abc/i.test(o.index); }; var highest = _.maxBy(jsonData, isValid); if (isValid(highest)) { console.log('The max value is: ' + highest.index); } else { console.log('No valid value found!'); } 
 <script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script> 

And this is how it works if there are no valid elements:

 var jsonDataWithoutValidValues = [{ "index": "xyz", }, { "index": "xyz", }]; var isValid = function(o) { return /abc/i.test(o.index); }; var highest = _.maxBy(jsonDataWithoutValidValues , isValid); if (isValid(highest)) { console.log('The max value is: ' + highest.index); } else { console.log('No valid value found!'); } 
 <script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script> 

This is probably a little weird to use in production, but I thought it was interesting enough to share.

+2
source

The following is a rough and unsatisfactory implementation:

 //filter out matching objects for possible future use var latest = ""; var matches = _.filter(jsonData, function (o) { var ret = /abc/i.test(o.index); if (ret) { var digits = o.index.replace(/\D/g,'') if (parseInt(digits) > latest) { latest = digits; latestIndex = o.index console.log(latest+">>>latestIndex") } return true; } return false; }); console.log("latestIndex->"+latest); } 
+1
source

In this case, you can simply use Array prototype sorting after you filter "abc" to sort them the way you want.

 var x = _.filter(jsonData, function (o) { return /abc/i.test(o.index); }).sort(function (a, b) { if(a.index > b.index) return -1; if(a.index < b.index) return 1; return 0; }); 

if you sort correctly you can get the highest value like

 console.log(x[0].index) 
+1
source

You can use one loop with Array#reduce and check the number if it exists.

 var data = [{ index: "xyz" }, { index: "abc1234" }, { index: "xyz" }, { index: "abc5678" }], getNumber = function (s) { return s.match(/^abc(\d+)/i)[1]; }, result = data.reduce(function (r, a) { return a.index.match(/^abc\d/i) && (!r || getNumber(r.index) < getNumber(a.index)) ? a : r; }, undefined); console.log(result); 
+1
source

Here's a lodash-bound approach:

 _(data) .map('index') .filter(_.method('match', /abc/)) .maxBy(_.flow(_.bindKey(/\d+/, 'exec'), _.first, _.toNumber)); 

Calling map() and filter() gives you a list of complaints with abc in them. Calling maxBy() finds max, but we need to compose a function to say that we want to compare it numerically. The flow() function is really convenient for this. Here we tell him to perform regular expression, find the first element of the result, and turn it into a number.

+1
source

Source: https://habr.com/ru/post/1266892/


All Articles