【问题标题】:javascript arrays with few fields compare比较少字段的javascript数组
【发布时间】:2013-10-12 12:42:22
【问题描述】:

我有两个数组(data 和 data_not_included)。这些数组的每个元素都有属性 id 和 name。我这样填充它们:

data[i] = {
           name :products.models[i].get('name'),
           id :  products.models[i].get('id')
          };

现在我想显示 data 中不在 data_not_included 数组中的元素。例如我有

data=[{name: Sugar}{id: 1},{name: Butter}{id: 2},{name: Cola}{id: 3}]
// and
data_nat_included = [{name: Sugar}{id: 1},{name: Butter}{id: 2}].

它应该只显示{name: Cola}{id: 3}

这是我已经完成的:

for(var j=0;j<data_not_icluded.length;j++)
{
    for(var i=0;i<data.length;i++)
    {
        if(data[i].id != data_not_icluded[j].id ){
          //but this doesnt work for me it displayes a lot of element many times
        }
     }
}

【问题讨论】:

  • }{ 应该是逗号以防止语法错误
  • 您真的需要通过 id 比较它们还是 == 测试就足够了(它们是相同的对象)?

标签: javascript arrays algorithm


【解决方案1】:

这两个答案都是渐近错误的。这意味着它们在次优时间运行。换句话说,它们是解决问题的幼稚方法。这个问题在数据库领域更广为人知,其中连接操作是司空见惯的。众所周知,连接的复杂度为O(log n * n + log m * m),其中n 是第一个表中的元素数,m 是第二个表中的元素数。这比其他示例O(n^2) 中提供的幼稚解决方案所需的操作更少。

但是,如果对您的数据有更多了解,例如,我希望这些值是唯一的并且易于序列化为字符串,您甚至可以通过简单地创建对象的哈希值来将复杂性降低到 O(n + m)想比较。操作方法如下:

其中n 是第一个数组中的元素数,m 是第二个数组中的元素数。

var data = [{ name: "Sugar" },
            { id: 1 },
            { name: "Butter" },
            { id: 2 },
            { name: "Cola" },
            { id: 3 }];
var dataNatIncluded = [{ name: "Sugar" },
                       { id: 1 },
                       { name: "Butter" },
                       { id: 2 }];

function join(a, b) {
    var hashA = {}, hashB = {}, p, result = [];
    function setter(hash) {
        return function (element) { hash[JSON.stringify(element)] = element; };
    }
    a.forEach(setter(hashA));
    b.forEach(setter(hashB));
    for (p in hashB) delete hashA[p];
    for (p in hashA) result.push(hashA[p]);
    return result;
}
// [{ name: "Cola" }, { id: 3 }]

【讨论】:

    【解决方案2】:

    一个简单的方法:

    var vals = [];
    
    for(var i=0;i<data.length;i++)
    {
        var found = false;
        for(var j=0;j<data_nat.length;j++)
        {
            if(data[i].id == data_nat[j].id ){
              found = true;
              break;
            }
         }
        if (!found) vals.push(data[i]);
    }
    

    JSFiddle

    【讨论】:

      【解决方案3】:
      for(var j=0;j<data_not_icluded.length;j++)
          for(var i=0;i<data.length;i++)
              if(data[i].id != data_not_icluded[j].id )
      

      想想这是做什么的:对于任何未包含的对象,显示与当前未包含对象具有不同 id 的所有对象。这将多次显示许多项目,并将显示“未包含”但位于另一个位置的对象。

      相反,循环遍历data,检查每个它是否不包含在data_not_included 中,否则显示它:

      dataloop: for (var i=0; i<data.length; i++) {
          for (var j=0; j<data_not_included.length; j++)
              if (data[i].id == data_not_icluded[j].id)
                  continue dataloop;
          display(data[i]);
      }
      

      或者,使用一些iteration methods of Arrays

      data.filter(function(d) {
          return data_not_included.every(function(n) {
              return d.id != n.id;
          });
      }).each(display);
      

      【讨论】:

      • 你,你刚刚把 O(log n * n + log m * m) 变成了 O(n^2)。了解如何加入:en.wikipedia.org/wiki/Sort-merge_join
      • @wvxvw: O(n*m),如果有的话。当然它不是很有效,但是 OP 并没有要求高性能,而是要求一个简单的解决方案:-)
      猜你喜欢
      • 2021-12-07
      • 2019-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多