web-dev-qa-db-fra.com

Convertir un tableau en tableau d'objets avec une réduction

optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']

result = [
  {start: bengaluru, end: salem},
  {start: salem, end: erode},
  {start: erode, end: tiruppur},
  {start: tiruppur, end: coimbatore},
]

Je veux convertir optimizedRoute en résultat. Je veux faire ceci avec ES6 .reduce(). Voici ce que j'ai essayé: 

const r = optimizedRoute.reduce((places, place, i) => {
  const result: any = [];
  places = []
  places.Push({
    startPlace: place,
    endPlace: place
  });
  // result.Push ({ startplace, endplace, seats: 4 });
  // console.log(result);
  return places;
}, {});
console.log(r)
24
kartik

Vous pouvez utiliser reduce pour obtenir le début et la fin d'une partie de l'itinéraire et renvoyer la fin pour le prochain début.

getParts = a => (                   // take a as array and return an IIFE
    r => (                          // with an initialized result array
        a.reduce((start, end) => (  // reduce array by taking two values
            r.Push({ start, end }), // Push short hand properties
            end                     // and take the last value as start value for next loop
        )),
        r                           // finally return result
    )
)([]);                              // call IIFE with empty array

const getParts = a => (r => (a.reduce((start, end) => (r.Push({ start, end }), end)), r))([]);

var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']

console.log(getParts(optimizedRoute));
.as-console-wrapper { max-height: 100% !important; top: 0; }


@EDIT Grégory NEUT ajout d'explication

// Two thing to know first :

// When no initial value is provided,
// Array.reduce takes the index 0 as first value and start to loop at index 1

// Doing (x, y, z)
// Will execute the code x, y and z

// Equivalent to :

// x;
// y;
// z;

let ex = 0;

console.log((ex = 2, ex = 5, ex = 3));

// So about the code

const getParts = (a) => {
  // We are creating a new function here so we can have an array where to
  // Push data to
  const func = (r) => {
    // Because there is no initial value
    //
    // Start will be the value at index 0 of the array
    // The loop is gonna start at index 1 of the array
    a.reduce((start, end) => {
      console.log(start, end);

      r.Push({
        start,
        end,
      });

      return end;
    });

    return r;
  };

  return func([]);
};

// Equivalent
const getPartsEquivalent = (a) => {
  const r = [];

  // Because there is no initial value
  //
  // Start will be the value at index 0 of the array
  // The loop is gonna start at index 1 of the array
  a.reduce((start, end) => {
    console.log(start, end);

    r.Push({
      start,
      end,
    });

    return end;
  });

  return r;
};

var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']

console.log(getPartsEquivalent(optimizedRoute));
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

14
Nina Scholz

Je ne comprends pas vraiment l'exigence "avec réduction", car le code correspondant utilisant une boucle est immédiatement lisible et ne nécessite aucune explication:

const optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
const result = new Array(optimizedRoute.length - 1);

for (let i = 0; i < result.length; ++i) {
  result[i] = {
    start: optimizedRoute[i],
    end: optimizedRoute[i + 1]
  };
}

console.log(result)

C'est amusant de faire des choses intelligentes parfois, mais certaines des réponses sont très compliquées comparées à cela!

11
Tom Fenech

Une autre approche consiste à utiliser la méthode map en combinaison avec slice. Pour la fonction map, vous devez passer une fonction callback en tant que argument qui sera appliqué à chaque élément de votre tableau .

optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
var result = optimizedRoute
                .slice(0, -1)
                .map((item, index) => ({start : item, end : optimizedRoute[index + 1]}));
console.log(result);

11

Voici un exemple avec reduce. Je ne suis pas sûr que ce soit la façon la plus naturelle de le faire!

Utiliser reduce me semble excessif et dans ce genre de cas (mais ce n'est que mon opinion), où j'utiliserais naturellement un index, eh bien, je choisirais une simple boucle for.

const optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
let startCity;
const result = optimizedRoute.reduce((acc, city) => {
  if(startCity) {
    acc.Push({start: startCity, end: city});
  }
  startCity = city;
  return acc;
}, []);

console.log(result);

4
sjahan

Puisque vous avez demandé reduce, voici une façon de le faire:

let optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
   
let res = optimizedRoute.reduce((accum, item, i)=>{
   if(i == optimizedRoute.length - 1) 
      return accum;
   accum.Push({start: item, end: optimizedRoute[i+1]})
   return accum;
}, [])

console.log(res);

3
giorgim

reduce ne correspond pas vraiment à la facture ici car vous n'essayez pas de réduire le tableau à une valeur unique.

Dans un monde parfait, nous aurions multi-tableau map version , généralement appelée Zip, que nous pourrions utiliser comme

const result = zipWith(optimisedRoute.slice(0, -1),
                       optimisedRoute.slice(1),
                       (start, end) => ({start, end}));

mais il n'y en a pas en JavaScript. La meilleure alternative est de map sur une plage d'index dans la route à l'aide de Array.from :

const result = Array.from({length: optimisedRoute.length - 1}, (_, index) => {
     const start = optimisedRoute[index];
     const end = optimisedRoute[index + 1];
     return {start, end};
});
3
Bergi

J'ai simplifié la réponse de nina scholz, Selon l’idée de nina, utilisez réduire pour obtenir le début et la fin d’une partie de l’itinéraire et renvoyer la fin pour le prochain début.

getParts = a => {
  const result = [];
    a.reduce((start, end) => {
      result.Push({ start, end });
      return end;
    });
    return result;
};
var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
console.log(this.getParts(optimizedRoute));
2
kartik

Le code suivant utilise Spread operator, Ternary operator et Array.reduce.

const optimizedRoute = [
  'Bengaluru',
  'Salem',
  'Erode',
  'Tiruppur',
  'Coimbatore',
];

// Look if we are at dealing with the last value or not
// If we do only return the constructed array
// If we don't, add a new value into the constructed array.

// tmp is the array we are constructing
// x the actual loop item
// xi the index of the item
const lastItemIndex = optimizedRoute.length - 1;

const ret = optimizedRoute.reduce((tmp, x, xi) => xi !== lastItemIndex ? [
  ...tmp,

  {
    start: x,
 
    // We access to the next item using the position of
    // the current item (xi)
    end: optimizedRoute[xi + 1],
  },
] : tmp, []);

console.log(ret);

2
Grégory NEUT

Je préfère la lisibilité plutôt que le code court qui le résout

optimizedRoute.reduce((routes, city, index) => {
  const firstCity = index === 0;
  const lastCity = index === optimizedRoute.length - 1;
  if (!firstCity) {
    routes.last().end = city;
  }
  if (!lastCity) {
    routes.Push({ start: city });
  }
  return routes;
}, []);

En outre, cette solution simplifiée mais qui rend la lecture moins lisible (du moins pour moi) pourrait être:

optimizedRoute.reduce((routes, city) => {
  routes.last().start = city;
  routes.Push({ end: city });
  return routes;
}, [{}]).slice(1, -1);

Et à propos de last(), c’est une fonction que j’utilise normalement pour la lisibilité:

Array.prototype.last = function() { 
  return this[this.length - 1] 
}
0
Francute