Bref historique: Beaucoup (la plupart?) De langages de programmation contemporains largement utilisés ont au moins une poignée d'ADT [types de données abstraits] en commun, en particulier,
chaîne (une séquence composée de caractères)
liste (une collection ordonnée de valeurs), et
type basé sur une carte (un tableau non ordonné qui mappe les clés aux valeurs)
Dans le langage de programmation R, les deux premières sont mises en œuvre comme characteret vector, respectivement.
Quand j'ai commencé à apprendre R, deux choses étaient évidentes presque dès le début: listest le type de données le plus important dans R (parce que c'est la classe parent pour le R data.frame), et deuxièmement, je ne pouvais tout simplement pas comprendre comment ils fonctionnaient, au moins pas assez bien pour les utiliser correctement dans mon code.
D'une part, il m'a semblé que le listtype de données de R était une implémentation simple de la carte ADT ( dictionaryen Python, NSMutableDictionaryen Objective C, hashen Perl et Ruby, object literalen Javascript, etc.).
Par exemple, vous les créez comme vous le feriez pour un dictionnaire Python, en passant des paires clé-valeur à un constructeur (ce qui n'est dictpas le cas en Python list):
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
Et vous accédez aux éléments d'une liste R comme vous le feriez pour ceux d'un dictionnaire Python, par exemple x['ev1']. De même, vous pouvez récupérer uniquement les «clés» ou simplement les «valeurs» en:
names(x) # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"
unlist(x) # fetch just the 'values' of an R list
# ev1 ev2 rv
# "10" "15" "Group 1"
x = list("a"=6, "b"=9, "c"=3)
sum(unlist(x))
# [1] 18
mais les R listsont également différents des autres ADT de type carte (parmi les langues que j'ai apprises de toute façon). Je suppose que c'est une conséquence de la spécification initiale pour S, c'est-à-dire une intention de concevoir un DSL [langage spécifique au domaine] de données à partir de zéro.
trois différences significatives entre R lists et les types de mappage dans d'autres langages largement utilisés (par exemple, Python, Perl, JavaScript):
tout d'abord , lists dans R est une collection ordonnée , tout comme les vecteurs, même si les valeurs sont saisies (c'est-à-dire que les clés peuvent être n'importe quelle valeur lavable et pas seulement des entiers séquentiels). Presque toujours, le type de données de mappage dans d'autres langues n'est pas ordonné .
deuxièmement , lists peut être renvoyé à partir de fonctions même si vous n'avez jamais passé un listlorsque vous avez appelé la fonction, et même si la fonction qui a renvoyé le listne contient pas de listconstructeur ( explicite) (Bien sûr, vous pouvez gérer cela en pratique en encapsulant le résultat retourné dans un appel à unlist):
x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x) # returns 'list', not a vector of length 2
# [1] list
Une troisième caractéristique particulière des R list: il ne semble pas qu'ils puissent être membres d'un autre ADT, et si vous essayez de le faire, le conteneur principal est contraint à a list. Par exemple,
x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
class(x)
# [1] list
mon intention ici n'est pas de critiquer la langue ou la façon dont elle est documentée; de même, je ne dis pas qu'il y a quelque chose de mal avec la liststructure des données ou comment elle se comporte. Tout ce que je veux, c'est corriger, c'est ma compréhension de leur fonctionnement afin que je puisse les utiliser correctement dans mon code.
Voici le genre de choses que j'aimerais mieux comprendre:
Quelles sont les règles qui déterminent quand un appel de fonction retournera un
list(par exemple,strsplitexpression récitée ci-dessus)?Si je n'attribue pas explicitement de noms à un
list(par exemple,list(10,20,30,40)) les noms par défaut sont-ils uniquement des entiers séquentiels commençant par 1? (Je suppose, mais je suis loin d'être certain que la réponse est oui, sinon nous ne pourrions pas contraindre ce type delistvecteur à un appel versunlist.)Pourquoi ces deux opérateurs différents,,
[]et[[]], renvoient-ils le même résultat?x = list(1, 2, 3, 4)les deux expressions renvoient "1":
x[1]x[[1]]pourquoi ces deux expressions ne renvoient-elles pas le même résultat?
x = list(1, 2, 3, 4)x2 = list(1:4)
Veuillez ne pas me diriger vers la documentation R ( ?list, R-intro) - je l'ai lue attentivement et cela ne m'aide pas à répondre au type de questions que j'ai récitées ci-dessus.
(enfin, j'ai récemment appris et commencé à utiliser un package R (disponible sur CRAN) appelé hashqui implémente un comportement de type carte conventionnel via une classe S4; je peux certainement recommander ce package.)
listdans R, n'est pas comme un hachage. J'en ai un de plus qui, à mon avis, mérite d'être noté. listdans R peut avoir deux membres avec le même nom de référence. Considérez que obj <- c(list(a=1),list(a=2))c'est valide et renvoie une liste avec deux valeurs nommées de 'a'. Dans ce cas, un appel à obj["a"]ne renverra que le premier élément de liste correspondant. Vous pouvez obtenir un comportement similaire (peut-être identique) à un hachage avec un seul élément par nom référencé en utilisant des environnements dans R. Par exemplex <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
x = list(1, 2, 3, 4), les deux ne renvoient PAS le même résultat:,x[1]etx[[1]]. Le premier renvoie une liste et le second renvoie un vecteur numérique. En faisant défiler ci-dessous, il me semble que Dirk était le seul répondant à répondre correctement à cette question.