Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populating array from a repeating array

I'm making a small tool for handling translations for a website. I already got this code working, but I feel there should be some more elegant and readable way using array methods (mine looks like a mess...).

Basically, I'll get input in the format shown in code (data_import, this is just fake data for testing). It has 4 columns [translationTag, uniqueId, languageId, translation]. Order of rows is same for every language and there is same number of rows for each language. Number of languages may change from 2 upwards.

the desired output would be like this:

const data_import =  [

  ['aaa', {id:1, langId:1, finnish:'tuntematon'}, {id:5, langId:4, english:'unknown'}, {id:9, langId:6, swedish:'okänd'}],
  ['bbb', {id:2, langId:1, finnish:'auto'}, {id:6, langId:4, english:'car'}, {id:10, langId:6, swedish:'bil'}],
  ['ccc', {id:3, langId:1, finnish:'polkupyörä'}, {id:7, langId:4, english:'bicycle'}, {id:11, langId:6, swedish:'cykel'}],
  ['ddd', {id:4, langId:1, finnish:'rullalauta'}, , {id:8, langId:4, english:'skateboard'}, {id:12, langId:6, swedish:'skateboard'}]
];

Here is my code that 'works' but is ugly and unreadable...

export const language = ['Finnish', 'Estonia', 'Polish', 'English', 'Spanish', 'Swedish'];

const data_import =  [
  ['aaa', 1, 1, 'tuntematon'],
  ['bbb', 2, 1, 'auto'],
  ['ccc', 3, 1, 'polkupyörä'],
  ['ddd', 4, 1, 'rullalauta'],
  ['aaa', 5, 4, 'unknown'],
  ['bbb', 6, 4, 'car'],
  ['ccc', 7, 4, 'bicycle'],
  ['ddd', 8, 4, 'skateboard'],
  ['aaa', 9, 6, 'okänd'],
  ['bbb', 10, 6, 'bil'],
  ['ccc', 11, 6, 'cykel'],
  ['ddd', 12, 6, 'skateboard']];

export const data = process_test(data_import);

function process_test(data) {  
  const numberOfCols = data[0].length;
  const idIndex = numberOfCols - 2;
  const arr_result = []
  let rowMax = 0;
  let rowMaxMulti = 0;
  let langIdLast = 0;
  data.forEach((row, index) => {
    // if = add non-language cols and first language column
    if(row[idIndex] === data[0][idIndex]) {
      rowMax = index + 1;
      const transItem = row.slice(0, idIndex-1);
      transItem.push({ id:row[idIndex], langId:row[idIndex], [language[row[idIndex] - 1]]:row[idIndex + 1] });
      arr_result[index] = transItem;
      langIdLast = row[idIndex];
    }
    // add other languages to datarow
    else {
      const transItem = { id:row[idIndex - 1], langId:row[idIndex], [language[row[idIndex] + 1]]:row[idIndex + 1] };
      if(langIdLast !== row[idIndex]) rowMaxMulti++;
      arr_result[index - rowMax * rowMaxMulti].push(transItem);
      langIdLast = row[idIndex];
    }
  })
  return(arr_result);
}
like image 912
Katzhuu Avatar asked Aug 26 '26 09:08

Katzhuu


1 Answers

It would be simpler to reduce into an object indexed by the translation tag, and then get that object's values. On each iteration, create an array for the translation tag if it doesn't already exist in the accumulator. Identify the language name from the langId of the current item, and push the new object to the array:

const language = ['Finnish', 'Estonia', 'Polish', 'English', 'Spanish', 'Swedish'];

const data_import =  [
  ['aaa', 1, 1, 'tuntematon'],
  ['bbb', 2, 1, 'auto'],
  ['ccc', 3, 1, 'polkupyörä'],
  ['ddd', 4, 1, 'rullalauta'],
  ['aaa', 5, 4, 'unknown'],
  ['bbb', 6, 4, 'car'],
  ['ccc', 7, 4, 'bicycle'],
  ['ddd', 8, 4, 'skateboard'],
  ['aaa', 9, 6, 'okänd'],
  ['bbb', 10, 6, 'bil'],
  ['ccc', 11, 6, 'cykel'],
  ['ddd', 12, 6, 'skateboard']];

const data = Object.values(data_import.reduce((a, [tTag, id, langId, word]) => {
  if (!a[tTag]) a[tTag] = [tTag];
  const langName = language[langId - 1];
  a[tTag].push({ id, langId, [langName]: word });
  return a;
}, {}));
console.log(data);
like image 75
CertainPerformance Avatar answered Aug 29 '26 00:08

CertainPerformance



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!