32 votes

Existe-t-il un moyen fonctionnel d'initialiser un tableau en JavaScript ES6 ?

J'ai finalement abandonné et j'ai écrit un for pour initialiser un simple tableau d'objets où chaque objet a un compteur incrémenté ( id ) comme un attribut de l'objet. En d'autres termes, je veux juste :

var sampleData = [{id: 1},{id: 2},...];

J'espérais une syntaxe compacte que je pourrais simplement mettre sur ma déclaration de revenus.

let sampleData = [];
for (var p = 0; p < 25; p++){
    sampleData.push({id: p});
}

return {
    data: sampleData,
    isLoading: true
};

52voto

Mark Meyer Points 31911

Array.from() est un bon moyen de le faire. Vous pouvez passer un {length: somlength} ou un autre objet de type tableau et une fonction qui définit chaque élément. Le premier argument (en l'appelant _ juste pour indiquer qu'il n'est pas utilisé) à cette fonction serait l'élément d'un tableau que nous avons transmis (mais nous n'avons transmis qu'une longueur donc cela ne signifie pas grand chose), le second i est l'index, qui est utilisé pour votre id :

let sampleData = Array.from({length: 10}, (_, id) => ({id}))

console.log(sampleData)

0 votes

Belle solution @Mark , j'avais pensé que le "underline" était un truc de lodash. Savez-vous où je peux trouver plus d'informations sur le "soulignement" et sa signification ?

5 votes

@Pete, ce que vous demandez à ce sujet - on dirait qu'un personnage n'est pas passé. J'ai ajouté un peu de _ c'est juste un argument de fonction -- on aurait pu l'appeler n'importe comment. J'utilise _ parfois pour des arguments qui seront inutilisés ou indéfinis.

1 votes

Oui, je voulais dire le trait de soulignement. Très élégant. Il faut bien sûr que je l'étoffe pour pouvoir le comprendre. Je vérifierai votre réponse dès que SO me le permettra.

17voto

jian Points 636

Voici ce que je fais habituellement :

const data = Array(10).fill().map((v, i) => ({id: i + 1}));
console.log({data});

fill garantit qu'il peut être utilisé avec map

0 votes

Cela semble équivalent à La solution de JohnP mais ceci fill() est plus rapide de 10 % que l'opérateur d'étalement ( fill() VS ... Test de JSBench.me ), mais toutes deux sont plus de 30 % plus lentes par rapport à l'option Mark's Array.from(...) solution .

9voto

JohanP Points 2218

Vous pouvez utiliser spread opérateur avec Array et ensuite faire correspondre chaque undefined à l'objet que vous voulez.

var arr = [...Array(10)].map((_,i)=>({id:i}));
console.log(arr)

0 votes

Pourquoi devez-vous utiliser l'opérateur d'étalement ? Est-ce parce que, sinon, vous feriez un mappage sur un tableau clairsemé vide, qui ne contient aucun élément ?

4 votes

Oui, Array(10) définit simplement le length il n'y a pas d'articles dedans.

2 votes

En supposant que [...Array(10)] est équivalent à Array(10).fill() Ce dernier n'est-il pas plus lisible ? Il est vrai que je n'ai pas une très bonne intuition de ce que les gens trouvent clair dans Javascript.....

7voto

naomik Points 10423

Vous cherchez un anamorphisme, ou un pliage inversé -

// unfold : ((r, state) -> List r, unit -> List r, state) -> List r
const unfold = (f, init) =>
  f ( (x, next) => [ x, ...unfold (f, next) ]
    , () => [] 
    , init
    )

// sampleData : List { id: Int }
const sampleData =
  unfold
    ( (next, done, i) =>
        i > 25
          ? done ()
          : next ({ id: i }, i + 1)
    , 0
    )

console .log (sampleData)
// [ { id: 0 }, { id : 1 }, ... { id: 25 } ]

Vous pouvez avoir une intuition sur la façon dont unfold fonctionne en le voyant utilisé dans d'autres programmes courants -

// unfold : ((r, state) -> List r, unit -> List r, state) -> List r
const unfold = (f, init) =>
  f ( (x, next) => [ x, ...unfold (f, next) ]
    , () => []
    , init
    )

// fibseq : Int -> List Int
const fibseq = init =>
  unfold
    ( (next, done, [ n, a, b ]) =>
         n === 0
           ? done ()
           : next (a, [ n - 1, b, a + b ])
    , [ init, 0, 1 ]
    )

console .log (fibseq (10))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

La mise en œuvre de unfold n'est qu'une possibilité. Bricolez et mettez-la en œuvre de la manière de votre choix -

// type Maybe a = Nothing | Just a    

// Just : a -> Maybe a
const Just = x =>
  ({ match: ({ Just: f }) => f (x) })

// Nothing : unit -> Maybe a
const Nothing = () =>
  ({ match: ({ Nothing: f }) => f () })

// unfold : (state -> Maybe (a, state), state) -> List a  
const unfold = (f, init) =>
  f (init) .match
    ( { Nothing: () => []
      , Just: ([ x, next ]) => [ x, ...unfold (f, next) ]
      }
    )

// fibseq : Int -> List Int
const fibseq = init =>
  unfold
    ( ([ n, a, b ]) =>
        n === 0
          ? Nothing ()
          : Just ([ a, [ n - 1, b, a + b ] ]) // <-- yikes, read more below
    , [ init, 0, 1 ]
    )

console .log (fibseq (10))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

J'ai triché un peu plus haut en utilisant un [] comme un tuple. Cela a permis de raccourcir le programme, mais il est préférable de modéliser explicitement les choses et de prendre en compte leurs types. Vous avez marqué cette question avec Programmation fonctionnelle Cela vaut donc la peine de faire un effort supplémentaire pour supprimer ce type de traitement implicite de nos programmes. En montrant cela comme une étape séparée, nous isolons une technique qui peut être appliquée non seulement à unfold mais pour tout programme que nous concevons -

// type Maybe a = Nothing | Just a
// type Tuple a b = { first: a, second: b }

// Just : a -> Maybe a
const Just = x =>
  ({ match: ({ Just: f }) => f (x) })

// Nothing : unit -> Maybe a
const Nothing = () =>
  ({ match: ({ Nothing: f }) => f () })

// Tuple : (a, b) -> Tuple a b
const Tuple = (first, second) =>
  ({ first, second })

// unfold : (state -> Maybe Tuple (a, state), state) -> List a  
const unfold = (f, init) =>
  f (init) .match
    ( { Nothing: () => []
      , Just: (t) => [ t.first, ...unfold (f, t.second) ] // <-- Tuple
      }
    )

// fibseq : Int -> List Int
const fibseq = init =>
  unfold
    ( ([ n, a, b ]) =>
        n === 0
          ? Nothing ()
          : Just (Tuple (a, [ n - 1, b, a + b ])) // <-- Tuple
    , [ init, 0, 1 ]
    )

console .log (fibseq (10))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

0 votes

Très belle implémentation d'un anamorpishm. Malheureusement, ana n'est parfois pas suffisante : tails("ana") donne ["ana", "na", "a", ""] . Cela ne peut pas être mis en œuvre avec ana comme Maybe ne fournit pas de valeur pour le cas de base. Si vous combinez Mabye con Either vous obtenez un morphisme encore plus général appelé apo . J'imagine apo comme le grand mais gentil frère de ana . Bonne (dé)pliologie :D

0 votes

Merci beaucoup, Bob. En effet, tails est difficile à mettre en œuvre avec ana mais c'est encore possible en utilisant un état composé. Merci de partager apo . J'aime être exposé à la théorie des catégories quand je peux le faire ; je n'ai pas assez de temps pour explorer ce sujet dense de manière trop approfondie par moi-même. Les autres lecteurs qui se sentent perdus peuvent commencer par lire sur apomorphisme .

0 votes

Btw, tu devrais me montrer comment écrire. tails en utilisant apo :D

4voto

stwilz Points 673

El .from() L'exemple est génial mais si vous voulez vraiment être créatif, regardez ceci.

const newArray = length => [...`${Math.pow(10, length) - 1}`]
newArray(2)
newArray(10)

Mais très limité

newArray(1000)
["I", "n", "f", "i", "n", "i", "t", "y"]

7 votes

Cela ne répond pas vraiment à la question, mais dans un esprit d'amusement et de créativité, faites un +1.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X