lodash / js:根据正则表达式过滤对象中的值,并通过比较获得最高值

时间:2017-04-19 05:58:23

标签: javascript lodash

对于以下json

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

我想分别过滤出abc值和xyz值。

我尝试了以下内容来获取值

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

它可以提供过滤后的输出。

现在我希望得到abc值中最高的值,如果值为abc123abc444abc999则代码应返回abc999

我可以使用lodash重新循环,但这可以在一次调用中完成 - 在过滤掉的同一个内部吗?

7 个答案:

答案 0 :(得分:4)

您可以使用Array.prototype.reduce()String.prototype.replace()RegExp /\D+/匹配并删除不是数字的字符。检查字符串的前一个数字部分是否小于字符串的当前数字部分

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);

答案 1 :(得分:2)

如果您想要找到最高的abc{SOME_NUMBER}值并同时进行过滤,则可以使用常规迭代而不是_.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 :(得分:2)

以下是粗略且不令人满意的实施:

//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);
}

答案 3 :(得分:2)

使用lodash执行此操作的一种方法是在代码中将filter替换为maxBy

当然,这有一个缺点,即如果集合中不存在有效元素,它将随意返回一个无效元素。因此,在获得结果后,需要进行额外的有效性检查。

这就是我在单独的函数中提取验证/过滤器代码的原因:



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>
&#13;
&#13;
&#13;

如果没有有效的元素,它的工作原理如下:

&#13;
&#13;
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!');
}
&#13;
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>
&#13;
&#13;
&#13;

在制作中使用这可能有点奇怪,但我觉得分享它很有趣。

答案 4 :(得分:1)

在这种情况下,你可以在过滤掉'abc'后按照你想要的方式对它进行排序

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;
  });

如果排序正确,您可以获得最高价值,如

console.log(x[0].index)

答案 5 :(得分:1)

您可以使用Array#reduce的单个循环并检查号码(如果存在)。

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);

答案 6 :(得分:1)

这是一种lodash链式方法:

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

map()filter()来电会为您提供包含abc的叮咬列表。 maxBy()调用找到最大值,但我们必须编写一个函数来告诉它我们想要用数字进行比较。 flow()函数对此非常方便。在这里,我们告诉它执行正则表达式,找到结果的第一个元素,然后将其转换为数字。