2

I started with a string:

hidden = "a,b,c,d,e,f,g,h";

I then split(",") the string into something I can try to work with:

array = hidden.split(",");

If I console.log out, the result is:

["a", "b", "c", "d", "e", "f", "g", "h"]

What I would eventually like to end up with (using JS only) is:

["a,b,c,d","e,f,g,h"];

or

[["a,b,c,d"],["e,f,g,h"]];

Thanks!

EDIT to show that I am actually trying to figure this out (don't mind the formatting):

if (currentPage === "view-bills.php")
{
var str = "";
hidden = document.getElementById("billItems");
array = hidden.value.split(",");
for (var i=0;i<array.length;i++)
{
str += "<option>"+ array[i] +"</option>";
}
var itemsAmt = document.getElementById("items").value;
document.getElementById("displayItems").innerHTML = "<optgroup label='"+ itemsAmt +" items'>" + str + "</optgroup>";
}

UPDATE:

The problem has been solved, however, I would like to show you the outcome of my project (accessing classes instead of id's this time):

http://i.imgur.com/umjhGPP.png ProjectResults

Once again, don't mind my formatting, I have trouble pasting things in here:

if (currentPage === "view-bills.php")
{
// Add items to select box
hidden = document.getElementsByClassName("billItems");
for (var n=0;n<hidden.length;n++)
{
array = hidden[n].value.split(",");
groups = [];
for(var i=0;i<array.length;i+=5)
{
groups.push(array.slice(i,i+5).join(','))
}
var str = "";
for (var j=0;j<groups.length;j++)
{
str += "<option>"+ groups[j] +"</option>";
}
var itemsAmt = document.getElementsByClassName("items")[n].value;
document.getElementsByClassName("displayItems")[n].innerHTML = "<optgroup label='"+ itemsAmt +" items'>" + str + "</optgroup>";
}
}
  • 2
    2 downvotes, why? it's a good question. – djechlin Nov 17 '14 at 20:45
  • 1
    @djechlin _this question does not show any research effort._ (I can see how this one is on the fence; this one feels too "gimme the code" for my taste.) – Evan Davis Nov 17 '14 at 20:46
  • @Mathletics it should be upvoted. I've already put enough research effort into doing this that I would rather there have been a solution on StackOverflow by now. Which there could be, if... this gets answered. – djechlin Nov 17 '14 at 20:47
  • 1
    In fact, if this were *my* question, I would have posted it before researching, then self-answered if I figured it out whether in 5 minutes or 30. – djechlin Nov 17 '14 at 20:48
  • This is going to become a meta-conversation about what SO is or is not. I stand by my downvote; the beauty of the community is that any/all are welcome to disagree and vote accordingly. – Evan Davis Nov 17 '14 at 20:50
  • I figured it would be easier to summarize my question to avoid causing confusion for others trying to read through a page of code, I don't see why that's a problem. –  Nov 17 '14 at 21:00
  • @Scott none of the code you posted is relevant to the problem though – Evan Davis Nov 17 '14 at 21:02

5 Answers5

4

You can use a regular expression:

var hidden = "aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii";
console.log(hidden.match(/(([^,]+,){0,3}[^,]+)/g));

Output

["aaa,bbb,ccc,ddd", "eee,fff,ggg,hhh", "iii"]  

See jsFiddle

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
  • @djechlin maybe you'd like to share them? – Evan Davis Nov 17 '14 at 20:55
  • @Mathletics regexes are hard to write (evidenced by the bug) and hard to read (evidenced by 5 upvotes before someone found a bug). I don't think throwing out a test case is going to produce a higher quality solution. – djechlin Nov 17 '14 at 20:58
  • @WouterHuysentruit alternate regex `/([^,](,*.){3})/g` http://jsfiddle.net/aLwc5vdh/2/ (treat the comma like an optional prefix) – Evan Davis Nov 17 '14 at 20:58
  • @djechlin minor bug fixed – huysentruitw Nov 17 '14 at 21:03
  • @Mathletics your regex doesn't work if only 1 additional item – huysentruitw Nov 17 '14 at 21:04
  • @WouterHuysentruit yes, I noticed that. Thanks for fixing it! – Evan Davis Nov 17 '14 at 21:04
  • 1
    This works when it comes to splitting the entire string, which would actually be the answer to my question; however, in my example a,b,c,d (and so on) were just placeholders for dynamic length strings, e.g.: 123,abcde,batm4n,kfc55. –  Nov 17 '14 at 21:08
1

An alternate way with a simple loop;

hidden = "a,b,c,d,e,f,g";
arr = hidden.split(",");
groups = []

for(var i = 0; i < arr.length; i+=4)
  groups.push(arr.slice(i,i+4).join(','))

console.log(groups)

> [ 'a,b,c,d', 'e,f,g' ]
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • @WouterHuysentruit Works with 'h' too, just demonstrating that it doesn't need even 4-groups. – Joachim Isaksson Nov 17 '14 at 20:56
  • For OP's sake you may want to initialize `groups`. – Evan Davis Nov 17 '14 at 20:57
  • @Mathletics Thanks, missed that :) – Joachim Isaksson Nov 17 '14 at 20:58
  • This is the best answer in terms of complexity and readability. – Evan Davis Nov 17 '14 at 21:07
  • Sorry to say, but a regex match is more readable, shorter and faster [see jsperf](http://jsperf.com/group-split-vs-match) – huysentruitw Nov 17 '14 at 21:27
  • @WouterHuysentruit I hope you didn't downvote based on that. They're both well over 1M ops/s (and I strongly disagree re:readability) so you're _really_ splitting hairs here. – Evan Davis Nov 18 '14 at 00:35
  • Needing to join part that have just been split doesn't feel right to me. It's misleading, thus less readable too me. Try to do that with a cake, it won't work :) – huysentruitw Nov 18 '14 at 07:55
  • It does feel weird when you put it like that, but in order to get the parts to act as an array to begin with (before it was a string), I had to split them. So the split creates the array, then we join the parts of the array that we want. Not entirely misleading. I have to try that with cake, I'm curious now. –  Nov 18 '14 at 12:46
0

This code takes the split version of the data and then groups it into groups of 4.

If there aren't exactly four items in the last group, it adds it after the for loop.

You could reduce repetition by extracting the join logic into a simple function so you aren't repeating the code (you would have to change both lines if you wanted to join with a different character, for example). I have kept the example rather procedural so you can get the general idea.

var hidden = "a,b,c,d,e,f,g,h";

var allItems = hidden.split(',');

var groups = [];
var currentGroup = [];

for (var i = 0; i < allItems.length; i++) {
    currentGroup.push(allItems[i]);

    if (currentGroup.length === 4) {
        groups.push(currentGroup.join(','));
        currentGroup = [];
    }
}

if (currentGroup.length > 0) {
    groups.push(currentGroup.join(','));
}

console.log(groups);

Result:

[ "a,b,c,d", "e,f,g,h" ]
Fenton
  • 241,084
  • 71
  • 387
  • 401
0

You can get it in a reduce e.g. via lodash:

return _.reduce(hidden.split(','), function(result, value, key) {
    if(key % 4 === 0) result.push("");
    result[result.length - 1] += value;
    return result;
}, []);

I think this is about the simplest solution you'll find, given the necessity of the chunk-every-fourth step.

djechlin
  • 59,258
  • 35
  • 162
  • 290
  • @Mathletics uh, dude, some people come to this page who are actually using said external library. They would like to know to use that solution. There certainly shouldn't be a duplicate of this question with the words "using lodash?" or "permitting external libraries?" attached. I'm not saying it should be the accepted answer (unless the OP is using node.js or something, in which case maybe!) but it should be available to readers. – djechlin Nov 17 '14 at 21:06
  • then leave it up _dude_, you can spare the rep. – Evan Davis Nov 17 '14 at 21:08
  • @Mathletics honestly, you probably enjoyed that downvote more than I did answering this question. I'm done answering questions here. Deleting my account in a few days. – djechlin Nov 17 '14 at 21:11
  • @AAA downvotes happen, don't delete your account for that. You seem to have a good reputation. But your answer here isn't the simplest solution :) – huysentruitw Nov 18 '14 at 08:00
  • Couple of things. First, you might want to indicate that using `Array#reduce` is also a possibility, for newbies who might not be able to see that for themselves, or those who don't know the meaning of "e.g." Second, this doesn't work, since you need to **return** result. –  Nov 18 '14 at 09:03
-3

So far I've just found the obvious loop:

var array = hidden.split(",");
var result = [];
for(var i = 0; i + 3 < array.length; i += 3) {
    result.push("" + array[i] + array[i+1] + array[i+2] + array[i+3]) + ",";
}
if(i < array.length) {
    var last = "";
    for(; i < array.length; i++) {
        last += array[i];
    }
    array.push(last);
}
djechlin
  • 59,258
  • 35
  • 162
  • 290