【问题标题】:Push to an array only if it isn't present already仅当它不存在时才推送到数组
【发布时间】:2013-12-27 01:48:09
【问题描述】:

我有几个复选框,它们根据选中的复选框过滤产品。单击复选框时过滤器起作用,并将产品 ID 添加到数组中。正如你所看到的,两个过滤器都有一些相同的 id,所以如果他们点击了多个输入框,我想确保这些 id 只被推送到数组中一次。例如。如果他们选择了 input.white 并选择了 input.greymelange,那么他们点击了 filter-btn 我只希望重复的 id 被推送一次。有什么办法可以做到吗?

JQUERY

var productIds = [""];

$(document).on('click', 'a.filter-btn', function(e){

    $( ".listingTemplate" ).html("");
   if ($('input.white').is(':checked')) {
          productIds.push("4021401143741", "4021402266227");
    } 

   if ($('input.greymelange').is(':checked')) {
          productIds.push("4021401143741", "4021402266227","4021402266418", "4021401143796");
    } 
});

HTML

 <input type="checkbox" id="white" class="white" value="white" />                
 <input type="checkbox" id="greymelange" class="greymelange" value="greymelange" />
<a href="#" class="filter-btn">filter</a>

【问题讨论】:

  • ...你到底想用这段代码做什么?我认为重新设计您的代码以循环遍历产品而不是过滤器会简化您的代码并且对数据库更加友好。

标签: jquery arrays push


【解决方案1】:

在添加到列表之前,您需要检查该项目是否包含在内。不幸的是,这并不像应有的那么简单,但以下堆栈解释了这一点:How do I check if an array includes an object in JavaScript?

由于您将其标记为 jQuery,因此以下(示例)代码可能适合您:

if ($.inArray("4021401143741", productIds) === -1)
   productIds.push("4021401143741");

有关此电话的更多信息see here。祝你好运!

【讨论】:

    【解决方案2】:

    你可以使用$.inArray()$.each()

    1) 将所有新值保存在一个数组中deArray
    2)使用$.each迭代这个数组,然后查找是否在productIds 使用inArray()

    if ($('input.greymelange').is(':checked')) {
            var deArray = ["4021401143741", "4021402266227", "4021402266418", "4021401143796"];
            $.each(deArray, function (i, j) {
                if ($.inArray(j, productIds) == -1) {
                    productIds.push(j);
                }
            });
        }
    

    建议:不要在数组中声明空字符串。

    var productIds = [""];  //considered as an string. This will affect 
                            //when you check length, now it is 1
    var productIds = []; //length is 0
    

    最后,

    var productIds = [];
    
    $(document).on('click', 'a.filter-btn', function (e) {
        $(".listingTemplate").html("");
        if ($('input.white').is(':checked')) {
            var dArray = ["4021401143741", "4021402266227"];
            $.each(dArray, function (i, j) {
                if ($.inArray(j, productIds) == -1) {
                    console.log(j)
                    productIds.push(j);
                }
            })
        }
    
            if ($('input.greymelange').is(':checked')) {
                var deArray = ["4021401143741", "4021402266227", "4021402266418", "4021401143796"];
                $.each(deArray, function (i, j) {
                    if ($.inArray(j, productIds) == -1) {
                        productIds.push(j);
                    }
                })
            }
                console.log(productIds)
            });
    

    JSFiddle

    【讨论】:

    • 嗨,不应该在某处的每个函数中使用 deArray 吗?
    • @user1937021 很好 :) 我已经更新了。应该用在each
    • @user1937021 我有一些拼写错误,我已经在这个小提琴中修复了它jsfiddle.net/74MAr
    【解决方案3】:

    要检查一个项目是否已经存在于数组中,您可以使用Array.indexOf。请注意,它在 IE

    var products = [];
    function addProducts() {
        for(var i = 0, l = arguments.length; i < l; i++) {
            if(products.indexOf(arguments[i]) === -1) {
                products.push(arguments[i]);
            }
        }
    }
    //Add indexOf if it doesn't exist natively
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(elt) {
            var len = this.length >>> 0;
            var from = Number(arguments[1]) || 0;
            from = (from < 0)
                 ? Math.ceil(from)
                 : Math.floor(from);
            if (from < 0)
              from += len;
    
            for(; from < len; from++) {
              if(from in this && this[from] === elt)
                return from;
            }
            return -1;
        };
    }
    

    然后要使用这些新功能,您可以将代码修改为:

    $(document).on('click', 'a.filter-btn', function(e) {
        if($('input.white').is(':checked')) {
            addProducts("4021401143741", "4021402266227");
        }
        if($('input.greymelange').is(':checked')) {
            addProducts("4021401143741", "4021402266227","4021402266418", "4021401143796");
        }
    });
    

    作为旁注。如果可以避免,则不应将事件绑定到文档。如果您使用大量事件,将事件绑定到文档可能会导致性能问题。每次触发click 事件时,都会运行此函数来检查目标是否与您指定的目标匹配。为了限制这种性能损失,您应该将它们绑定到最近的不变元素。在表单内的输入示例中,您可以将其添加到表单中。

    【讨论】:

      【解决方案4】:

      将以下代码添加到 ischecked 条件中。 // Continue execution 用于推送值。

      isSet = false;
      currentVal = '999999999999';
      $.each(productIds, function( index, value ) {
        if(value == currentVal){
           isSet = true;
        }
      });
      
      if(isSet){
      // Continue execution
      } else {
      // failure
      }
      

      【讨论】:

        【解决方案5】:

        它需要是一个数组吗?听起来您最好使用普通对象:

        productIds[ 420… ] = true;
        

        这取决于您的代码的其余部分,但听起来您想要实现哈希/查找表/字典而不是数组 - 以这种方式检查是否存在也更直接。

        【讨论】:

          【解决方案6】:

          如果您只有一组固定的产品 ID,为什么需要一个可变长度的数组来存储检查了哪些产品 ID?

          我建议也许构建一个包含您可以使用的逻辑的对象。

          function productMapper() {
              var colorToIdMap = {
                  'white' = [
                      '4021401143741',
                      '4021402266227'
                  ],
                  'greymelange' = [
                      '4021401143741',
                      '4021402266227',
                      '4021402266418',
                      '4021401143796'
                  ]
              };
              var selectedIds = [];
              function selectIds(color) {
                  this.selectedIds = [];
                  var colorIds = this.colorToIdMap[color];
                  for(i = 0; i < colorIds.length; i++) {
                     var currentId = colorIds[i];
                     if(this.selectedIds.indexOf(currentId) === -1) {
                         this.selectedIds.push(currentId);
                     }
                  }
              }
              function getSelectedIds() {
                  return this.selectedIds;
              }
          }
          

          用法可能是:

          var selectedProductMap = new productMapper();
          
          $(document).on('click', 'a.filter-btn', function(e){
          
              $( ".listingTemplate" ).html("");
              if ($('input.white').is(':checked')) {
                    selectedProductMap.selectIds('white');
              } 
          
              if ($('input.greymelange').is(':checked')) {
                    selectedProductMap.selectIds('greymelange');
              } 
          });
          

          这里的好处是,当您添加新颜色和产品 ID 时,很容易将它们添加到此类(或从数据库动态构建类的那部分。

          我还建议考虑重构 HTML,这样您就不需要为每个颜色选项添加 if 条件。也许给所有复选框输入一个公共类并从输入属性派生颜色值。您的 onclick 函数中可能会出现这样的情况:

          $('input.filterCheckbox').each(function(index.value)) {
              var $currentCheckbox = $(this);
              if($currentCheckbox.is(':checked')) {
                  selectedProductMap.selectIds($currentCheckbox.val());
              }
          }
          
          var currentlySelectedIds = selectedProductMap.getSelectedIds();
          

          【讨论】:

            猜你喜欢
            • 2016-09-01
            • 2011-04-12
            • 1970-01-01
            • 2021-12-03
            • 1970-01-01
            • 2016-08-03
            • 2011-05-05
            • 2013-06-14
            • 2017-03-20
            相关资源
            最近更新 更多