-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!

3
  • @mplungjan, well i guess you did not see that i tried to find a solution, but hey, thanks! Commented Dec 30, 2022 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! Commented Dec 30, 2022 at 15:30
  • Well I did it anyway because I found it interesting and it is xmas Commented Dec 30, 2022 at 15:59

1 Answer 1

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>

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

6 Comments

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!
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
Here it is the code but with a bigger list: jsfiddle.net/62pfmt0k and this is some of the code, but working as i said in description - jsfiddle.net/qha9y2bx . @ChrisG, do you see the difference? mplungjan, thanks again!
@Crys See updated. I only add the files attr on the last now
@ChrisG I added the files attr to every line. I fixed that now
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.