【问题标题】:.filter() same data from different sources [duplicate].filter() 来自不同来源的相同数据[重复]
【发布时间】:2018-11-11 17:04:26
【问题描述】:

我有 2 个数组:

var yin =  [{"_id": "11111", "name": "blue"}];
var yang = [{"_id": "11111", "name": "blue"}, {"_id": "22222", "name": "red"}];

我尝试像这样过滤掉以下内容:

var yang = yang.filter(function(e){ return this.indexOf(e) < 0; }, yin);

由于某种原因,indexOf(e) 正在返回 -1,我知道这是完全相同的数据。我能想到的唯一一件事是有一些关系(可能不是正确的术语)数据位于下面,这使得它们看起来不一样,因为对象来自完全不同的数据库来源。

是否有另一种方法可以从来自不同来源的对象数组中过滤出相同的数据?

我知道这个过滤功能有效,因为如果我使用.push() 推送数据,它会很好地过滤掉。

【问题讨论】:

  • this 不是你想象的那样。在您的代码中,this 指的是全局对象。
  • 我认为this 可能正在做你想做的事。
  • 你到底想做什么
  • 我不理解这条评论@samanime
  • OP 将yin 作为第二个参数传递给filter,它指的是函数调用中的this。所以它是正确使用的。

标签: javascript react-native


【解决方案1】:

您需要 sam 对象引用来比较对象。

var object = { _id: "11111", name: "blue" },
    yin =  [object],
    yang = [object, { _id: "22222", name: "red" }];

yang = yang.filter(function(e){ return this.indexOf(e) < 0; }, yin);

console.log(yang)

通过同化对象的相同键来不引用对象。

var yin =  [{ _id: "11111", name: "blue" }],
    yang = [{ _id: "11111", name: "blue" }, { _id: "22222", name: "red" }];

yang = yang.filter(o => !yin.some(p => Object.keys(o).every(k => o[k] === p[k])));

console.log(yang);

【讨论】:

    【解决方案2】:

    这会奏效。

    var new = yang.filter((yang) => {
        for (let i = 0; i < yin.length; i++) {
          if (yin[i]._id==yang._id) {
            return yang;
          }
        }
      });
    

    【讨论】:

      【解决方案3】:

      问题:

      var yin =  [{"_id": "11111", "name": "blue"}];
      yin.indexOf({"_id": "11111", "name": "blue"}) // return -1
      

      所以,我建议使用一个新功能来过滤您需要的字段。

      带箭头功能:

      yang.filter( e => yin.some(a => (a._id == e._id && a.name == e.name)));
      

      无箭头功能:

      yang.filter( function(elementYang) {
          return yin.some(function(elementYing) {
              return (elementYang._id == elementYing._id) && (elementYang._name == elementYing._name);
          });
      });
      

      【讨论】:

        【解决方案4】:

        问题是两个不同的对象永远不会在您的意思中相等。您需要对对象进行深入比较(手动),或者如果它适合您的需要,您可以检查相等的 _id 属性。

        var yin =  [{"_id": "11111", "name": "blue"}];
        var yang = [{"_id": "11111", "name": "blue"}, {"_id": "22222", "name": "red"}];
        
        yang = yang.filter(function(e){ 
        return this.findIndex(function(y){return y._id === e._id}) < 0; }, yin);
        
        console.log(yang);

        【讨论】:

          【解决方案5】:

          问题是它们没有相同的对象。

          他们拥有看起来相同的对象。

          举个简单的例子,看看这个:

          console.log({} == {});
          console.log({} === {});

          请注意,即使这些对象看起来完全相同,但它们并不相等。与原语(字符串、数字)不同,对象都是独一无二的。

          您需要做的是实现您自己的contains() 函数,该函数将对对象中的每个属性进行比较:

          const yin =  [{"_id": "11111", "name": "blue"}];
          const yang = [{"_id": "11111", "name": "blue"}, {"_id": "22222", "name": "red"}];
          
          function contains(arr, el) {
            return arr.some(i => equal(i, el));
          }
          
          function equal(a, b) {
            return Object.keys(a).length === Object.keys(b).length
              && Object.entries(a).every(([key, val]) => a[key] === b[key]);
          }
          
          // or !contains() if you want the difference
          const result = yang.filter(function(el) { return contains(this, el) }, yin);
          
          console.log(result);

          那里的equal() 函数只进行浅层比较。如果对象更复杂,您将需要一些能够执行深度相等并递归所有元素的东西。幸运的是,这个功能已经在许多流行的库和独立的 Node 模块中实现了很多选项,所以你不必自己实现它。

          【讨论】:

          • 感谢您花时间写出深思熟虑的解释。虽然您的回答确实完美,但我更喜欢 Gabrieles 的简单性。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多