1

I need to create an array of arrays. I had a pretty extensive if/else cycle working, but I think I can refactor it down using jQueries nextUntil function. Based on what I'm seeing, I'm on the right track, but my results are just shy of what I need in both directions.

Here's the HTML

var array = [[]];

<ul id="list">
    <li class="get-it">1</li>
    <li class="get-it">2</li>
    <li class="ignore-it">3</li>
    <li class="get-it">4</li>
    <li class="get-it">5</li>
    <li class="ignore-it">6</li>
    <li class="get-it">7</li>
    <li class="get-it">8</li>
    <li class="ignore-it">9</li>
    <li class="get-it">10</li>
    <li class="get-it">11</li>
</ul>

And here's a couple of ways I've tried to scrape the .get-it list items

// returns single-item array of all .get-it items
array.push( $( '#list' ).children().nextUntil( '.ignore-it' );

// returns 8 single-item array of .get-it items
$row.children().nextUntil( '.ignore-it' ).each(function(){
    array.push( $(this) );
});

Here's what I actually need returned

// what I need returned
array = [
    [ li[0], li[1] ],
    [ li[3], li[4] ],
    [ li[6], li[7] ],
    [ li[9], li[10] ]
]
Alexander Ivanov
  • 2,143
  • 1
  • 12
  • 15
NominalAeon
  • 593
  • 5
  • 23

2 Answers2

3

This will work:

var array = $('.get-it:first, .ignore-it + .get-it').map(function() {
    return $(this).add($(this).nextUntil('.ignore-it'));
}).get();

JSFiddle

Basically it works like this:

// grab the first .get-it, as well as all .get-it
// elements that follow an .ignore-it element
$('.get-it:first, .ignore-it + .get-it')

// map each of those items into an array that contains
// itself, plus all .get-it elements up until the next
// .ignore-it element
.map(function() {
    return $(this).add($(this).nextUntil('.ignore-it'));
})

// convert our jQuery collection into a regular array
.get();
jmar777
  • 38,796
  • 11
  • 66
  • 64
  • Yes, I think this is doing the thing! I'm pluggin it in, bonus points* for using nuxtUntil. *no actual bonus points awarded. – NominalAeon Oct 15 '14 at 14:50
  • This is catching singles, but then also the doubles. There's not really a pattern to it that I can discern. I tried breaking it into two calls $('.get-it:first') and $('.ignore-it + .get-it'), so I've whittled it down to being the latter's fault. More to come – NominalAeon Oct 15 '14 at 15:34
  • 1
    Not sure I follow. What pattern is it failing on? – jmar777 Oct 15 '14 at 15:40
  • It's failing on the second pattern. The first pattern gives a double (correctly). The second pattern then gives two single items, then a double, then a double, two singles, then a double. I have twelve items in the list currently. I tried switching it to $('.ignore-it').next('.get-it') and got the exact same results. – NominalAeon Oct 15 '14 at 15:44
  • 1
    Can you give me a link to an updated http://jsfiddle.net/x1ewcfLk/ with the markup that's causing it to fail? – jmar777 Oct 15 '14 at 15:46
  • 1
    Perhaps I misunderstood you, but is this is the markup pattern you're talking about (http://jsfiddle.net/x1ewcfLk/1/)? As best I can tell, the code works fine with that as well. – jmar777 Oct 15 '14 at 15:58
  • Nope, I apologize, there was a bug in the markup. Cleaned it up and this is working perfectly, thank you! – NominalAeon Oct 15 '14 at 16:34
1

You can do this

var array = [], tempArr = $('#list > li.get-it').map(function(){ return $(this); });
while(tempArr.length > 0)
   array.push(tempArr.splice(0, 2));  // splice it into two

DEMO

What the above does is get the elements and slice them into two.

Amit Joki
  • 58,320
  • 7
  • 77
  • 95
  • 1
    This is clean. Just one (potential) caveat is that it's of course restricted to markup where there's always two `.get-it`'s before the `.ignore-it`. It was unclear from the question if that's a guarantee or not. – jmar777 Oct 15 '14 at 14:52
  • Thank you, I should have put it in the original post, but I need to acount for varialbe item length between .ignore-it. Sometimes there are two, sometimes there are five. – NominalAeon Oct 15 '14 at 14:54