문제

Ok this may be a simple loop question that I'm just overthinking (would be far from the first time) but I'm going to post this just incase someone has a quick answer for me.

I have an array of DOM elements like this:

<ul id="array">
  <li class='item' data-id="1">
    <ul class="child">
      <li class='item' data-id="2"></li>
      <li class='item' data-id="3"></li>
    </ul>
  </li>
  <li class='item' data-id="4"></li>
  <li class='item' data-id="5">
    <ul class="child">
      <li class='item' data-id="6"></li>
      <li class='item' data-id="7">
        <ul class="child">
          <li class='item' data-id="8"></li>
          <li class='item' data-id="9"></li>
          ...
        </ul>
      </li>
    </ul>
  </li>
</ul>

I want to loop through that using jQuery and come out with something like:

var result = [
  {
    "id":1,
    "children":[
      {
        "id":2,
        "children":[]
      }, 
      {
        "id":3,
        "children":[]
      }
    ]
  },
  { 
    "id": 4,
    "children":[]
  },
  {
    "id": 5,
    "children":[
      {
        "id":6,
        "children":[]
      }, 
      {
        "id":7,
        "children":[
          {
            "id":8,
            "children":[]
          }, 
          {
            "id":9,
            "children":[]
          }
        ]
      }
    ]
  }
]

(Note that is obviously spaced out for easy reading :) )

If that was the exact number of child ul items there would be, that would be an easy loop. The issue I'm having is that the list item tree could go as many levels down as a user wants (realistically, it will stop at some point but you get the idea) so it will need to continue to loop through the tree until there are no more.

도움이 되었습니까?

해결책

You'll need a recursive function and map() method for this:

function extract() {
    var $this = $(this);

    return {
        id: $this.data('id'),
        children: $this
            .find('> .child > .item')
            .map(extract)
            .get()
    };
}

var output = $('#array > .item')
    .map(extract)
    .get();

Demo: http://jsfiddle.net/pj2C2/1/

다른 팁

This worked for me:

function arrayRecursive($arr) {
    var result = [];

    // with > .item you go only 1 level deeper per step
    $arr.find('> .item').each(function(index, item) {
        var obj = {};
        obj.id = $(item).attr('data-id');
        obj.children = arrayRecursive($(item).find('.child'));
        result.push(obj);
    });

    return result;
}

var result = arrayRecursive($('#array'));

// Test the result with a stringified alert
alert(JSON.stringify(result));

EDIT: Removed the if ($(item).find('.child').length > 0) so you have empty arrays as default.

Sounds like a recursion problem.

So you can loop through the li elements check to see if the child is a ul element if so another level of recursion else store the value at that level.

Some rough pseudo code

readElements($("#array").children());

function readElements(array) {
    var elementsArray = [];
    for (var i = 0; i < array.length; i++) {
       if ($($(array[i]).children()[0]).is("ul")) {
           return readElements($(array[i]).children());
       }
       elementsArray.push({ id: getId(), children: [] });
       // add id elementArrays
    }
    return elementsArray;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top