2015-11-10 1 views
3

En Javascript, on pourrait utiliser indexOf pour obtenir la première instance d'un élément donné dans un tableau.Comment obtenir le premier index d'un élément donné dans Array/List in Elm?

Quelle est la meilleure façon de le faire dans Elm?

array = Array.fromList ["Stack","Overflow","is","","awesome"] 
element = "" 

indexOf element array = 
    -- should return 3 

Que faire si nous avons une liste au lieu d'un tableau?

+0

Pourquoi avez-vous besoin de l'index de l'élément? –

+0

@FrankSchmitt Imaginez un jeu de puzzle coulissant où vous pouvez passer la position de départ via la chaîne de requête: http://moroshko.github.io/sliding-puzzle. La chaîne de requête peut ressembler à: '? Start = 3,2,1,6,5,4,, 8,7'. Le modèle dans le jeu doit connaître l'emplacement de la tuile vide. Donc, mon idée est de diviser 'start' par', ', puis de le convertir en tableau, puis de trouver la position de la chaîne vide. Pensez-vous qu'il existe une meilleure façon de représenter la position de départ dans l'URL? (les carreaux peuvent contenir plus d'un caractère, donc les virgules) –

+0

Sons sensés. Je me demandais juste parce que dans les langages fonctionnels, les index list/array sont rarement nécessaires IME. –

Répondre

6

Il existe un module tiers elm-list-extra qui fournit cette fonction. "elemIndex".

+0

Merci! Un lien serait utile. –

+0

http://package.elm-lang.org/packages/circuithub/elm-list-extra/3.7.0/List-Extra#elemIndex – Apanatshka

6

Juste pour le plaisir, voici une version roulées à la main pour la liste:

helper : List a -> a -> Int -> Int 
helper lst elem offset = 
    case lst of 
    []  -> -1 
    x :: xs -> 
     if x == elem then offset 
     else helper xs elem (offset + 1) 

indexOf lst element = 
    helper lst element 0 

helper recherche récursivement la liste pour l'élément, en gardant une trace du nombre d'éléments que nous avons visités jusqu'à présent. Pour la liste vide, elle renvoie -1. Si vous n'aimez pas les constantes magiques, vous pouvez facilement changer le type de retour en Maybe Int et renvoyer Nothing à la place.

Et voici un programme complet de l'utiliser (il suffit de copier + coller dans le REPL en ligne à elm-lang.org.

import Html exposing (text) 

lst = ["Stack","Overflow","is","","awesome"] 
element = "" 

helper : List a -> a -> Int -> Int 
helper lst elem offset = 
    case lst of 
    []  -> -1 
    x :: xs -> 
     if x == elem then offset 
     else helper xs elem (offset + 1) 

indexOf lst element = 
    helper lst element 0 

main = 
    text (toString (indexOf lst ""))  
2

prendre une autre, la composition des fonctions de bibliothèque de base, je trouve cela plus lisible que récursion, et plus déclarative; il est juste un pipeline simple de transformations de données la structure de données est le dernier paramètre, de sorte que vous pouvez appliquer partiellement la valeur que vous cherchez, comme idxOfFoo = firstIndexOf "foo"

indicesOf : a -> List a -> List Int 
indicesOf thing things = 
    things 
    |> List.indexedMap (,) 
    |> List.filter (\(idx, item) -> item == thing) 
    |> List.map fst 


firstIndexOf : a -> List a -> Int 
firstIndexOf thing things = 
    indicesOf thing things 
    |> List.minimum 
    |> Maybe.withDefault -1 


lastIndexOf : a -> List a -> Int 
lastIndexOf thing things = 
    indicesOf thing things 
    |> List.maximum 
    |> Maybe.withDefault -1 

session REPL:..En un coup d'œil, je pense que ceci est similaire en complexité à l'implémentation de CircuitHub dans List.Extra.

+0

Je reçois une erreur avec ceci: 'Impossible de trouver la variable 'fst' |> List.map fst ' – Spiralis