【问题标题】:How to find and remove duplicate entry from dropdown list [duplicate]如何从下拉列表中查找和删除重复条目[重复]
【发布时间】:2023-03-11 02:19:02
【问题描述】:

我有一个包含重复条目的下拉列表。重复条目之一是下拉列表中的选定值。例如:

<select id="country">
  <option value="NZ">New Zealand</option> //New Zealand is selected option
  <option value="USA">United States</option>
  <option value="Ind">India</option>
  <option value="NZ">New Zealand</option>
  <option value="SA">South Africa</option>
  <option value="UK">United Kingdom</option>
 <option value="JP">Japan</option>
</select>

现在,我试图删除新西兰选项(重复),但同时,我试图选择新西兰的另一个条目,以便我将列表视为:

<select id="country">

  <option value="USA">United States</option>
  <option value="Ind">India</option>
  <option value="NZ" selected>New Zealand</option> //removing the duplicate selection.
  <option value="SA">South Africa</option>
  <option value="UK">United Kingdom</option>
 <option value="JP">Japan</option>
</select>

这是用于填充下拉列表的 JavaScript:

$.ajax('/url/allcountries', {
    method:'GET',
    success: function(items){               
        if(items){
          var items = items;
           $.each(items, function(i, item) {
             $("#country").append($('<option></option>').val(item.code).html(item.name));
            //Eg: where item.code = "USA" and item.name ="United States"

            if($("#country :selected").text() === item.code){
                $("#country :selected").html(item.name);
                //Edit as per suggested
                var x = {};
                $("select[id='country'] > option").each(function () {
                 if(x[this.text]) {
                    $(this).remove();
                 } else {
                  x[this.text] = this.value;
                }
            });
               //this gives me a duplicate entry at the top of the list.
             }
          });
      } //if condition ends
   }//success ends
});

关于如何删除重复项并仅选择它们的任何想法?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    你可以这样试试:

    [].slice.call(country.options)
      .map(function(a){
        if(this[a.innerText]){ 
          country.removeChild(a); 
        } else { 
          this[a.innerText]=1; 
        } 
      },{});
    

    JSFIDDLE DEMO

    或者像这样在 Jquery 中:

    var x = {};
    $("select[name='country'] > option").each(function () {
        if(x[this.text]) {
            $(this).remove();
        } else {
            x[this.text] = this.value;
        }
    });
    

    【讨论】:

    • 没有帮助我...我尝试了你上面建议的方式...对我来说仍然一样..我放错了吗?
    • @user1234 他的回答旨在清理列表,删除重复的选项在它们被创建并附加到 DOM 之后。在 .each() 之后,您可能会运行它,可能会使用超时
    【解决方案2】:

    在附加选项元素之前。检查是否有另一个具有相同值的元素,如果有,请检查它并移至下一个选项。

    success: function(items){               
            if(items){
              var items = items;
               $.each(items, function(i, item) {
                 if($('option[value='+item.code+']').length!==0){
                 $('option[value='+item.code+']')[0].selected='true';
                 return 0;
                 }
                 $("#country").append($('<option></option>').val(item.code).html(item.name));
                //Eg: where item.code = "USA" and item.name ="United States"
    
                if($("#country :selected").text() === item.code){
                    $("#country :selected").html(item.name);
                    //Edit as per suggested
                    var x = {};
                    $("select[id='country'] > option").each(function () {
                     if(x[this.text]) {
                        $(this).remove();
                     } else {
                      x[this.text] = this.value;
                    }
                });
                   //this gives me a duplicate entry at the top of the list.
                 }
              });
          } //if condition ends
       }//success ends
    

    【讨论】:

      【解决方案3】:

      您只需要在$.each() 之前创建一组独特的项目。这可以通过许多不同的方式来完成。这是one way 来做的。

      编辑


      (2019 年 11 月 24 日)

      &lt;option value="NZ"&gt;New Zealand&lt;/option&gt; //New Zealand is selected option

      不,不是。标记不显示option 上的selected 属性。它可能看起来已被选中,因为它是列表中的第一个条目,并且没有选择 option 元素。

      也许您希望“新西兰”出现在“印度”之后。您可以按该顺序放置option,将其标记为selected,然后它将显示在select 中,同时出现在“印度”之后的列表中,您不能允许任何内容是selected 并在“India”之后插入“New Zealand”option,但它不会显示在select 中(就在下拉菜单中列表中,第一个option 将显示在选择中(但实际上不是selected))。

      在大多数情况下,需要一个特定的排序顺序和默认选择。最常见的替代方法是什么都没有 selected 并添加 disabled option 作为列表中的第一个条目(使用空文本或占位符,例如“请选择一个国家/地区”)。后者非常简单,但我认为最初的问题最好通过前者的行为来解决。

      因此,您需要一种方法来告诉$.each() 的回调函数在添加option 时标记selected。我最初的答案是处理问题根源的正确方法(列表中的重复条目)。如果从未添加它们,则无需清理它们。列出不同的国家/地区列表,然后致电$.each()

      这是我最喜欢的使数组与众不同的新方法:

      arr = [...new Set(arr)]

      所以,在 2019 年重写这个...

      // If you want to specify a default selection, modify `toOption` as such...
      //const defaultSelection = 'NZ'; 
      //const toOption = c => 
      //    new Option(c.name, c.code, c.code === defaultSelection, c.code === selected);
      const toOption = c => 
          new Option(c.name, c.code, false, c.code === selected);    
      
      const country= document.querySelector('#country');
      
      // If you wish to retain previously selected country...
      //const idx = country.selectedIndex;
      //const selected = idx > -1 ? country.options[idx].value : null;
      const selected = 'NZ';
      
      while (country.firstChild) country.firstChild.remove();
      
      const resp = await fetch('/url/allcountries');
      
      [...new Set((await resp.json()).items)]
          .map(toOption).forEach(country.appendChild);
      

      我可能会使用两个注释掉的块。结合它们将允许始终保留先前的选择,同时在没有任何选择时默认为您选择的选择。

      注意.items 附加到.json()。这些示例假设您的 api 响应的类型为 application/json,并且在根目录下有一个数组 items

      {
          "items": [{
              "code": "USA",
              "name": "United States"
          }, {
              "code": "Ind",
              "name": "India"
          }, {
              "code": "NZ",
              "name": "New Zealand"
          }, {
              "code": "SA",
              "name": "South Africa"
          }, {
              "code": "UK",
              "name": "United Kingdom"
          }, {
              "code": "JP",
              "name": "Japan"
          }]
      }
      

      这还假定您的响应对象将具有 items 属性,即 Array,即使为空 ({ "items": [] })。我认为这是一个安全的假设,因为这是一个非 CORS 请求,这意味着您很可能可以控制服务器,因此您可以确保返回一个空列表,而不是 nullfalse 等。否则,您需要将响应 JSON 保存到变量中,然后将 if 语句添加回...

      const resp = await fetch(...)
      const json = await resp.json();
      
      if (json && json.items /*&& json.items.length */) 
          json.items.map(...).forEach(...);
      

      ...与optional chaining...

      json?.items?.map(...).forEach(...);
      

      最后,您可能会从服务器返回一个选定的选项。

      {
          "items": [{
              "code": "USA",
              "name": "United States",
              "isDefault": true                <---default
          }, {
              "code": "Ind",
              "name": "India"
          }, {
              "code": "NZ",
              "name": "New Zealand",
              "selected": true                 <---currently selected
          }, {
              "code": "SA",
              "name": "South Africa"
          }, {
              "code": "UK",
              "name": "United Kingdom"
          }, {
              "code": "JP",
              "name": "Japan"
          }]
      }
      

      在这种情况下,其中一项会有一些标志表明这一点,Options 的实例化将变为...

      new Option(c.name, c.code, c.code === defaultSelection, c.selected)
      

      您可能需要使用selected: !falsey 考虑多个项目。默认情况下,匹配此条件的最后一个项目将是生成的选定选项。

      我还添加了一个假设的isDefault。它将允许服务器设置默认选择。

      new Option(c.name, c.code, c.isDefault, c.selected)
      

      由此产生的肉和土豆(目前只能在没有 polyfills/babel/etc. 的 Chrome [也许是 Opera] 中工作):

      async function updateCountries() {
          const country= document.querySelector('#country');
          
          while (country.firstChild) country.firstChild.remove();
      
          const resp = await fetch('/url/allcountries');
          const json = await resp.json();
      
          [...new Set(json?.items)]             
              .map(c => new Option(c.name, c.code, c.isDefault, c.selected))
              .forEach(country.appendChild);
      }
      

      免责声明:此代码绝对没有在所有主流浏览器以及所有中士和下士浏览器中测试过

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-30
        • 1970-01-01
        • 2013-03-09
        • 1970-01-01
        相关资源
        最近更新 更多