J'ai un tableau de tableaux similaire à la structure ci-dessous. J'essaie de réduire le tableau aussi efficacement que possible en fonction du nom de la société (ex. Société A). Donc, fondamentalement, lorsque les noms de société sont les mêmes, combinez le tableau interne afin que les numéros de chaque position soient ajoutés aux numéros du tableau correspondant dans la position correspondante. De plus, si l'un des tableaux contient un e-mail ou un téléphone manquant, prenez la position de l'e-mail ou du téléphone qui a une valeur. Le tableau de résultats en bas montre le résultat que j'essaie d'atteindre.

* Remarque - Je ne connais pas la longueur des numéros suivant une entreprise. La longueur est définie dynamiquement, mais la longueur de chaque tableau interne sera toujours la même. Donc, parfois, tous les tableaux internes sont de 6 valeurs, d'autres fois ils peuvent être de 20 valeurs.

var array = [
    [Company A, A-Email, A-Phone, 2, 5, 10],
    [Company A, A-Email, , 1, 10, 7],
    [Company A, , A-Phone, 3, 2, 4],
    [Company B, B-Email, , 1, 10, 7],
    [Company B, B-Email, B-Phone, 5, 10, 8],
    [Company C, C-Email, C-Phone, 3, 2, 1]
  ]
var resultArray = [
    [Company A, A-Email, A-Phone, 6, 17, 21],
    [Company B, B-Email, B-Phone, 6, 20, 15],
    [Company C, C-Email, C-Phone, 3, 2, 1]
  ]

Donc, à l'origine, j'essayais quelque chose comme ça parce que le tableau avait déjà été trié par nom d'entreprise:

for (var i = 0; i < array.length - 1; i++) {
  var firstArray = array[i]
  var nextArray = array[i + 1]
  if (nextArray[0] == firstArray[0]) {
    for (var t = 3; t <= firstArray.length; t++) {
      firstArray[t] = firstArray[t] + nextArray[t]

    }
    resultArray.push(firstArray);
} else {continue;}

J'ai un grand ensemble de données et le faire de cette façon était vraiment lourd et ma fonction a expiré, donc je ne suis pas complètement sûr que cela fonctionne. J'ai commencé à essayer de faire une méthode de réduction avec une table de hachage mais je ne pouvais pas vraiment le comprendre. Vous avez une idée sur la façon de le faire le plus efficacement possible?

De plus, je ne peux pas utiliser jQuery, donc purement vanilla javascript s'il vous plaît.

1
MattMcCode 17 avril 2018 à 19:22

3 réponses

Meilleure réponse

Vous pouvez utiliser ES6 reduce pour résumer le tableau en un objet. Et utilisez Object.values pour convertir l'objet en un tableau.

Remarque: Fiddle ne fonctionne pas (actuellement). Vous devrez donc peut-être le tester sur votre navigateur.

var array=[['Company A','A-Email','A-Phone',2,5,10],['Company A','A-Email',,1,10,7],['Company A',,'A-Phone',3,2,4],['Company B','B-Email',,1,10,7],['Company B','B-Email','B-Phone',5,10,8],['Company C','C-Email','C-Phone',3,2,1]];

var resultArray = Object.values(array.reduce((c, v) => {
  c[v[0]] = c[v[0]] || [v[0], null, null].concat(new Array(v.length - 3).fill(0));

  c[v[0]][1] = c[v[0]][1] || v[1]; //Update Email
  c[v[0]][2] = c[v[0]][2] || v[2]; //Update Phone

  //Loop thru the numbers and add
  for (var i = 3; i < v.length; i++) c[v[0]][i] += ( v[i] || 0 );
  return c;
}, {}));

console.log(resultArray);
3
Eddie 17 avril 2018 à 16:55

Les tables de hachage seraient la bonne approche (en supposant que la «société A», etc. sont des chaînes; sinon c'est une carte).

var companies = {};
for ( var i = 0; i < array.length; i++ ) {
    var item = array[ i ];
    var name = item[ 0 ];
    var phone = item[ 1 ];
    var num1 = item[ 2 ];
    var num2 = item[ 3 ];
    var num3 = item[ 4 ];
    if ( companies[ name ] ) {
        var record = companies[ name ];
        record[ 1 ] = record[ 1 ] || email;
        record[ 2 ] = record[ 2 ] || phone;
        record[ 2 ] += num1;
        record[ 3 ] += num2;
        record[ 4 ] += num3;
    } else {
        companies[ name ] = [ name, email, phone, num1, num2, num3 ]
    }
}
var resultArray = Object.values( companies );
0
Ben West 17 avril 2018 à 16:36

Vous pouvez essayer quelque chose comme ci-dessous. L'essentiel est d'utiliser reduce() pour obtenir un objet plein de données correctes puis de l'aplatir en tableaux à l'aide de Object.values().

//initial data  
var data = [
  ['Company A', 'A - Email', 'A - Phone', 2, 5, 10],
  ['Company A', 'A - Email', , 1, 10, 7],
  ['Company A', , 'A - Phone', 3, 2, 4],
  ['Company B', 'B - Email', , 1, 10, 7],
  ['Company B', 'B - Email', 'B - Phone', 5, 10, 8],
  ['Company C', 'C - Email', 'C - Phone', 3, 2, 1]
];

//reduce function to organize data
var reducer = function(accumulator, currentValue, currentIdx) {
  var [companyId, email, phone, i, j, k] = currentValue;
  accumulator[companyId] = {
    email: !accumulator[companyId] ? email : !accumulator[companyId].email ? email : accumulator[companyId].email,
    phone: !accumulator[companyId] ? phone : !accumulator[companyId].phone ? phone : accumulator[companyId].phone,
    i: (accumulator[companyId] ? accumulator[companyId].i : 0) + i,
    j: (accumulator[companyId] ? accumulator[companyId].j : 0) + j,
    k: (accumulator[companyId] ? accumulator[companyId].k : 0) + k
  }

  return accumulator;
}
var rawData = data.reduce(reducer, {});

//organize data back into array of arrays
var formattedData = [];
for (key in rawData) {
  formattedData.push([key].concat(Object.values(rawData[key])));
}

console.log(formattedData);
0
Tom O. 17 avril 2018 à 18:02