1

I want to find div element that contain custom attribute mod than append that div to list item. But first I have to remove divs that contain duplicate mod value. Here's what I have done

<div class="list"></div>

<div class="container">
    <div mod="dog"></div>
    <div mod="man"></div>
    <div mod="woman"></div>
    <div mod="dog"></div>
    <div mod="bird"></div>
    <div mod="insects"></div>
    <div mod="dog"></div>
</div>

this is my script

modArr($('.container').find('[mod]'))

function modArr(el){
        var filterArray = [] // store mod
        ,   modNames = [] // store mod value
        ,   arrIndex = [] // store non duplicate index
        ,   li = [] // store
        modArray = el

        // store mod value
        for(var i=0; i < modArray.length; i++){
            modNames.push($(modArray[i]).attr('mod')) // get mod value from div
        }

        // search for non duplicate mod value and get the index of none duplicate mod
        for(var i=0; i < modArray.length; i++){
            if(filterArray.indexOf(modNames[i]) === -1){
                filterArray.push(modNames[i])
                arrIndex.push(i) // push non duplicate index value
            }
        }

        filterArray = [] // reset filterArray

        // push module from modArray to filterArray using index in arrIndex
        for(var i=0; i < arrIndex.length; i++){
            filterArray.push(modArray[arrIndex[i]])
        }

        // push to li array
        $.each(filterArray,function(i,el){
            li[i] = '<li>'+ el.outerHTML +'</li>'
        })

        $('<ul></ul>')
            .append(li.join(''))
            .appendTo('.list')

    }

What you can see is that I've used to many loops, is there any simple way to do this. Thanks!

3
  • So, do you want to remove all the duplicated instances or want to keep one of them? Commented Apr 7, 2017 at 8:17
  • I want to keep want of them Commented Apr 7, 2017 at 8:34
  • pagedemos.com/qcjkz8mqaq2r is a very fast way of doing this Commented Apr 7, 2017 at 8:41

2 Answers 2

1

We can use an object as a map for checking duplicates, see comments (I've added text to the mod divs so we can see them):

modArr($('.container').find('[mod]'));

function modArr(elements) {
  // A place to remember the mods we've seen
  var knownMods = Object.create(null);
  // Create the list
  var ul = $("<ul></ul>");
  // Loop the divs
  elements.each(function() {
    // Get this mod value
    var mod = this.getAttribute("mod");
    // Already have one?
    if (!knownMods[mod]) {
      // No, add it
      knownMods[mod] = true;
      ul.append($("<li></li>").append(this.cloneNode(true)));
    }
  });
  // Put the list in the .list element
  ul.appendTo(".list");
}
<div class="list"></div>

<div class="container">
    <div mod="dog">dog</div>
    <div mod="man">man</div>
    <div mod="woman">woman</div>
    <div mod="dog">dog</div>
    <div mod="bird">bird</div>
    <div mod="insects">insects</div>
    <div mod="dog">dog</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

We can also just use the DOM to check for duplicates, but it's a bit slower (not that it matters for the number of elements here):

modArr($('.container').find('[mod]'));

function modArr(elements) {
  // Create the list
  var ul = $("<ul></ul>");
  // Loop the divs
  elements.each(function() {
    // Get this mod value
    var mod = this.getAttribute("mod");
    // Already have one?
    if (ul.find('div[mod="' + mod + '"]').length == 0) {
      // No, add it
      ul.append($("<li></li>").append(this.cloneNode(true)));
    }
  });
  // Put the list in the .list element
  ul.appendTo(".list");
}
<div class="list"></div>

<div class="container">
    <div mod="dog">dog</div>
    <div mod="man">man</div>
    <div mod="woman">woman</div>
    <div mod="dog">dog</div>
    <div mod="bird">bird</div>
    <div mod="insects">insects</div>
    <div mod="dog">dog</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


Note: I used this.cloneNode(true) rather than outerHTML because there's no need to take a roundtrip through markup. If you want more jQuery there, it's $(this).clone(); ;-) Similarly, if you don't like this.getAttribute("mod"), there's $(this).attr("mod").


I'd be remiss if I didn't point out that mod is an invalid attribute name for div elements. You can use any name you want starting with data-, though, so perhaps use <div data-mod="dog"> instead.

Sign up to request clarification or add additional context in comments.

1 Comment

Nicely explained! I'll use <div data-mod="dog"> instead. Thank you! :)
1

Try this, only adds if an element with mod is not already in list:

$('.list').append('<ul>');
$('.container [mod]').each(function(index, el) {
  if($('.list [mod=' + $(el).attr('mod') + ']').length === 0) {
    $('.list ul').append($('<li>' + el.outerHTML + '</li>'));
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="list"></div>

<div class="container">
    <div mod="dog">Dog1</div>
    <div mod="man">Man1</div>
    <div mod="woman">Woman1</div>
    <div mod="dog">Dog2</div>
    <div mod="bird">Bird1</div>
    <div mod="insects">Insect1</div>
    <div mod="dog">Dog3</div>
</div>

1 Comment

Thank you for your answer, this is the answer I was looking for also. But I voted T.J Crowder answer because he explain it thoroughly. Thanks! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.