-3

I have a list like this: 125,248,11,486,3554,89,55

I need to have 2 textarea, in the first one i need to put the above list and after i click a button then in the second textarea i will get a list like this:

<!--startline-->[new text="table" ids="125,248,11"]
<!--startline-->[new text="table" files="2" ids="486,3554,89,55"]

So these are the rules:

  • i need chunk size of 3 elements
  • i need to add custom text before and after the chunk: <!--startline-->[new text="table" ids=" + chunk + "]
  • if the last chunk has 2 or 1 element, then i need to merge it with the previous one and the generated text for that chunk will be: <!--startline-->[new text="table" files="2" ids=" + chunk + "]
  • every custom text and chunk will be on a new line, like in the above example

I found something that could help, using .slice or .splice but the problem is that i need to add custom text and not making an array like here: https://stackoverflow.com/a/47061736/1773862

So, any ideas? :)

----------- Solution:

const myList = document.getElementById('mylist');
const myNewList = document.getElementById('mynewlist');
const chunkSize = 3;
checkpoint = 0;
document.getElementById('generate').addEventListener('click', () => {
  let chunks = myList.value.trim().split(',').reduce((all, one, i) => {
    const ch = Math.floor(i / chunkSize);
     all[ch] = [].concat((all[ch] || []), one);
     checkpoint++;
     return all
  }, []);
  let lastChunk = [...chunks[chunks.length-1]]; 
  const lastone = chunks.length-2;
  //alert(lastone);
  if (lastChunk.length < chunkSize) {
    chunks = chunks.slice(0, -1);
    chunks[chunks.length - 1] = chunks[chunks.length - 1].concat(lastChunk);
    checkpoint = 1;
  }
  myNewList.value = chunks.map((chunk,i) => `<!--startline-->[new text="table" ids="${chunk.join(',')}"]`).join('\n');
  
   var content = myNewList.value;
   var lastLine = content.substr(content.lastIndexOf("\n")+1);
  var countnow = (lastLine.match(/,/g)||[]).length;
  if (countnow > 2) {  
  var elem = document.getElementById('mynewlist');
 var val  = elem.value.split(/(\r\n|\n|\r)/g).filter(function(n){return n.trim()});
 val.pop();
 elem.value = val.join('\r\n');
 lastLine = lastLine.replace("\"table\" ", "\"table\" \"files=\"2\" ");
 elem.value += "\n" + lastLine;
 }
  
});
<textarea id="mylist">30318,30319,30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,123,999</textarea>
<br><br>
<button id="generate">Generate new list</button>
<br><br>
<textarea id="mynewlist" style="width: 538px; height: 294px;"></textarea>

Thanks to @mplungjan for the first part of the solution!

Crys
  • 67
  • 2
  • 9
  • @mplungjan, well i guess you did not see that i tried to find a solution, but hey, thanks! – Crys Dec 30 '22 at 15:25
  • @mplungjan i am not here to impress you, it's not a contest. I just asked for some help, not to do my work ;) so thanks a bunch. Have a nice day! – Crys Dec 30 '22 at 15:30
  • Well I did it anyway because I found it interesting and it is xmas – mplungjan Dec 30 '22 at 15:59

1 Answers1

1
  1. Use split
  2. Use a chunker - I found one at Split array into chunks
  3. You can use template literals to generate the strings

This one ONLY adds the files attribute on the last and ONLY if it has more than the chunksize

const chunker = (list, size) => list.value.trim().split(',').reduce((acc, cur, i) => { const ch = Math.floor(i / size); acc[ch] = [].concat((acc[ch] || []), cur); return acc }, []);

const myList = document.getElementById('mylist');
const myNewList = document.getElementById('mynewlist');
const chunkSize = 3;
document.getElementById('generate').addEventListener('click', () => {
  let chunks = chunker(myList, chunkSize),
    lastChunk = [...chunks[chunks.length - 1]], 
    partial = lastChunk.length < chunkSize,
    max = chunks.length-2; // max is only used if partial
  if (partial) {
    chunks = chunks.slice(0, -1); // chop the last off
    chunks[chunks.length - 1] = chunks[chunks.length - 1].concat(lastChunk); // concat to new last chunk
  }
  myNewList.value = chunks.map((chunk, i) => `<!--startline-->[new text="table"${partial && i===max ? ' files="2"' : '' } ids="${chunk.join(',')}"]`).join('\n')

});
#mynewlist {
  width: 700px;
  height: 300px;
}
<textarea id="mylist">30318,30319,30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,123,999</textarea>
<br><br>
<button id="generate">Generate new list</button>
<br><br>
<textarea id="mynewlist"></textarea>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • This works, but has a little bug: the 'files="2"' part needs to be only if the the last chunk has 2 or 1 element and only on the final chunk. Thank you for the help. I will try to solve the bug, i am used to use "while" in cases like this but i am not familiar with .map. I will search for more details about .map and see how it works. Thank you again! – Crys Dec 30 '22 at 16:46
  • The code is doing exactly what you asked tho. The last chunk has only 1 element in this example and you said that if that was the case, then it should merge with the previous one and that last chunk should have the `files=2` custom text – Chris G Dec 30 '22 at 17:59
  • Here it is the code but with a bigger list: https://jsfiddle.net/62pfmt0k/ and this is some of the code, but working as i said in description - https://jsfiddle.net/qha9y2bx/ . @ChrisG, do you see the difference? mplungjan, thanks again! – Crys Dec 30 '22 at 18:59
  • @Crys See updated. I only add the files attr on the last now – mplungjan Dec 31 '22 at 05:57
  • @ChrisG I added the files attr to every line. I fixed that now – mplungjan Dec 31 '22 at 06:12
  • yeah I saw the difference on a larger list – Chris G Jan 02 '23 at 11:02