【问题标题】:How to get first instance of each string?如何获取每个字符串的第一个实例?
【发布时间】:2019-06-03 11:52:37
【问题描述】:

在 jQuery 中是否有一种方法可以找到包含第一个字符串实例的每个元素?

<ul>
    <li>1</li> <-- find this
    <li>1</li>
    <li>1</li>
    <li>2</li> <-- find this
    <li>2</li>
    <li>3</li> <-- find this
    <li>3</li>
    <li>3</li>
    <li>3</li>
</ul>

【问题讨论】:

  • 嗯.. 结果应该是什么? &lt;li&gt; 元素的节点元素?或者只是节点值(即像 [1, 2, 3] 这样的数组)?
  • 节点元素
  • 最好的方法是遍历节点和存储的 innerHTML 数组
  • 在 jQuery 中没有为此的内置函数。如果可以的话,您可能应该重新设计构建此 HTML 的部分。

标签: javascript jquery


【解决方案1】:

一种选择是使用Set 对象来跟踪&lt;li&gt;。使用filter 获取在Set 对象上找不到的所有&lt;li&gt; 对象。

$(function() {
  var found = new Set();
  var firstLI = $("ul > li").filter(function() {
    var text = $(this).text().trim();
    if (!found.has(text)) {
      found.add(text);
      return true;
    }

    return false;
  });

  //Testting
  firstLI.addClass("first");
});
.first {
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
  <li>1</li> <!-- find this -->
  <li>1</li>
  <li>1</li>
  <li>2</li> <!-- find this -->
  <li>2</li>
  <li>3</li> <!-- find this -->
  <li>3</li>
  <li>3</li>
  <li>3</li>
</ul>

【讨论】:

  • 很棒的解决方案。喜欢 Set 的用法
  • 您需要在使用Set 之前检查浏览器兼容性。一个更兼容的方式来做同样的事情是var obj = {}obj[key] = true; 向集合中添加一些东西,if (obj[key]) 来检查成员资格。
  • 基于 Doc,Set 的基本用法甚至与 IE 11 兼容。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/….. 或者您也可以使用 profiler(只是为了确定):)
【解决方案2】:

一种可能的解决方案是使用.filter() 来获取text() 与之前的li's 文本不同的元素。请注意,此解决方案仅在列表中的 strings 排序后才能正常工作,正如您在输入示例中提供的那样。

$(document).ready(function()
{
    var items = $("#ulList li").filter(function()
    {
        return $(this).prev().text() !== $(this).text();
    });

    items.css("background-color", "skyblue");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="ulList">
    <li>1</li>
    <li>1</li>
    <li>1</li>
    <li>2</li>
    <li>2</li>
    <li>3</li>
    <li>3</li>
    <li>3</li>
    <li>3</li>
</ul>

【讨论】:

  • 如果列表可以保证排序,那么这将正常工作。
【解决方案3】:

您可以使用 map() + get() 返回元素的 HTML 数组。

然后,使用[...new Set(Array)] 将其过滤到唯一的项目。

var elems = $("ul > li").map(function() { return this.outerHTML }).get();
$("ul").html( [...new Set(elems)].join("\n") ); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
    <li>1</li>
    <li>1</li>
    <li>1</li>
    <li>2</li>
    <li>2</li>
    <li>3</li>
    <li>3</li>
    <li>3</li>
    <li>3</li>
</ul>

作为一个可重用的函数:

const removeDuplicatesFrom = (selector) => {
  const $e = $(selector);
  if (!$e.length) return;

  const children = $e.children().map(function() { return this.outerHTML }).get();
  $e.html([...new Set(children)].join("\n"));
};

removeDuplicatesFrom("ul");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
  <li>1</li>
  <li>1</li>
  <li>1</li>
  <li>2</li>
  <li>2</li>
  <li>3</li>
  <li>3</li>
  <li>3</li>
  <li>3</li>
</ul>

【讨论】:

  • 您需要在使用...Set 之前检查浏览器兼容性。
  • @jnylen 不确定这是针对我还是针对 OP。 OP 没有指定浏览器限制,所以我认为先发制人地阻碍我对 Internet Explorer 兼容性的回答是没有用的。虽然如果是这种情况,他们可以选择不使用它。
【解决方案4】:
$("ul li").each(function(){
    if ($(this).prev("li").html() != $(this).html()){
        $(this).addClass("first");
    }
});

演示: https://codepen.io/seyyedmojtaba72/pen/qGgRxG

【讨论】:

    【解决方案5】:

    我试着做一个简单的例子:

    const values = new Set()
    
    $("li").each((idx, element) => {
      values.add(element.textContent)
    })
    
    for (let value of values) {
      $(`li:contains('${value}'):first`).addClass("first")
    }
    .first {
      color: red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <ul>
        <li>1</li>
        <li>1</li>
        <li>1</li>
        <li>2</li>
        <li>2</li>
        <li>3</li>
        <li>3</li>
        <li>3</li>
        <li>3</li>
    </ul>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-11
      • 1970-01-01
      • 2011-03-26
      • 2017-12-01
      • 2015-07-02
      • 1970-01-01
      相关资源
      最近更新 更多