Jak poprawnie używać list w języku R?


320

Krótkie tło: Wiele (najbardziej?) Współczesnych języków programowania w powszechnym użyciu ma co najmniej garstkę ADT [abstrakcyjnych typów danych], w szczególności:

  • ciąg (sekwencja złożona ze znaków)

  • lista (uporządkowany zbiór wartości) oraz

  • typ oparty na mapie (nieuporządkowana tablica odwzorowująca klucze na wartości)

W języku programowania R pierwsze dwa są realizowane odpowiednio jako characteri vector.

Kiedy zacząłem uczyć się R, dwie rzeczy były oczywiste prawie od samego początku: listjest to najważniejszy typ danych w R (ponieważ jest to klasa nadrzędna dla R data.frame), a po drugie, po prostu nie mogłem zrozumieć, w jaki sposób działały nie wystarczająco dobrze, aby używać ich poprawnie w moim kodzie.

Po pierwsze, wydawało mi się, że listtyp danych R był prostą implementacją mapy ADT ( dictionaryw Pythonie, NSMutableDictionaryw Celu C, hashw Perlu i Ruby, object literalw Javascript i tak dalej).

Na przykład, tworzysz je tak jak w słowniku Pythona, przekazując pary klucz-wartość do konstruktora (co dictnie jest w Pythonie list):

x = list("ev1"=10, "ev2"=15, "rv"="Group 1")

I uzyskujesz dostęp do elementów Listy R, tak jak do słownika Python, np x['ev1']. Podobnie można pobrać tylko „klucze” lub tylko „wartości” poprzez:

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

ale R listsą również inne niż inne ADT typu mapowego (spośród języków, których i tak się nauczyłem). Domyślam się, że jest to konsekwencja początkowej specyfikacji S, tj. Zamiaru zaprojektowania od podstaw danych DSL danych / statystyk [język specyficzny dla domeny].

trzy znaczące różnice między R listi typami odwzorowań w innych językach w powszechnym użyciu (np. Python, Perl, JavaScript):

po pierwsze , lists w R są kolekcją uporządkowaną , podobnie jak wektory, nawet jeśli wartości są kluczowane (tzn. klucze mogą być dowolnymi wartościami mieszającymi, a nie tylko kolejnymi liczbami całkowitymi). Prawie zawsze typ danych mapowania w innych językach jest nieuporządkowany .

po drugie , lists mogą zostać zwrócone z funkcji, nawet jeśli nigdy nie przeszedłeś, listkiedy wywołałeś funkcję, i nawet jeśli funkcja, która zwróciła listnie zawiera (jawnego) listkonstruktora (Oczywiście możesz sobie z tym poradzić poprzez: zawijanie zwróconego wyniku w wywołanie do 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

Trzecia cecha szczególna od R: lists: to nie wydaje się, że mogą być członkami innego ADT, a jeśli staramy się robić to pierwotny pojemnik jest zmuszany do list. Na przykład,

x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)

class(x)
# [1] list

nie zamierzam tu krytykować języka ani sposobu jego dokumentowania; podobnie nie sugeruję, że coś jest nie tak ze liststrukturą danych lub z jej zachowaniem. Chcę tylko poprawić, rozumiem, w jaki sposób działają, dzięki czemu mogę poprawnie używać ich w kodzie.

Oto rzeczy, które chciałbym lepiej zrozumieć:

  • Jakie reguły określają, kiedy wywołanie funkcji zwróci list(np. strsplitWyrażenie wyszczególnione powyżej)?

  • Jeśli nie przypisuję jawnie nazw do list(np. list(10,20,30,40)), Czy domyślne nazwy są tylko liczbami całkowitymi zaczynającymi się od 1? (Zakładam, ale nie jestem pewien, czy odpowiedź brzmi tak, w przeciwnym razie nie bylibyśmy w stanie zmusić tego typu listdo wektora z wywołaniem unlist.)

  • Dlaczego te dwa różne podmioty, []i [[]]przywróć sam wynik?

    x = list(1, 2, 3, 4)

    oba wyrażenia zwracają „1”:

    x[1]

    x[[1]]

  • dlaczego te dwa wyrażenia nie zwracają tego samego wyniku?

    x = list(1, 2, 3, 4)

    x2 = list(1:4)

Proszę nie kierować mnie do Dokumentacji R ( ?list, R-intro) - Przeczytałem ją uważnie i nie pomaga mi to w odpowiedzi na pytania, które przytoczyłem powyżej.

(na koniec niedawno się nauczyłem i zacząłem używać pakietu R (dostępnego w CRAN), hashktóry implementuje konwencjonalne zachowanie typu mapy za pośrednictwem klasy S4; z pewnością mogę polecić ten pakiet.)


3
Z x = list(1, 2, 3, 4), oba NIE zwracają tego samego wyniku:, x[1]i x[[1]]. Pierwszy zwraca listę, a drugi zwraca wektor numeryczny. Przewijając poniżej, wydaje mi się, że Dirk był jedynym respondentem, który poprawnie odpowiedział na to pytanie.
IRTFM,

2
Nie zauważyłem, żeby ktoś rozwinął na twojej liście sposobów, że listw R nie jest jak skrót. Mam jeszcze jedną, którą uważam za wartą odnotowania. listw R może mieć dwóch członków o tej samej nazwie odniesienia. Zastanów się, że obj <- c(list(a=1),list(a=2))jest poprawny i zwraca listę z dwiema nazwanymi wartościami „a”. W tym przypadku wywołanie for obj["a"]zwróci tylko pierwszy pasujący element listy. Możesz uzyskać zachowanie podobne (może identyczne) do skrótu z tylko jednym elementem na nazwy, do których się odwołujesz, używając środowisk w R. np.x <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
russellpierce

1
W ciągu ostatnich 6 miesięcy ponownie przeczytałem ten post z odpowiedziami trzy razy i za każdym razem znajdowałem więcej oświecenia. Świetne pytanie i kilka świetnych odpowiedzi. Dziękuję Ci.
Rich Lysakowski PhD

Odpowiedzi:


150

Aby odpowiedzieć na ostatnią część pytania, ponieważ naprawdę wskazuje to na różnicę między listai vectorR:

Dlaczego te dwa wyrażenia nie zwracają tego samego wyniku?

x = lista (1, 2, 3, 4); x2 = lista (1: 4)

Lista może zawierać dowolną inną klasę jako każdy element. Możesz więc mieć listę, w której pierwszy element jest wektorem znaków, drugi ramką danych itp. W tym przypadku utworzono dwie różne listy. xma cztery wektory, każdy o długości 1. x2ma 1 wektor o długości 4:

> length(x[[1]])
[1] 1
> length(x2[[1]])
[1] 4

Są to więc zupełnie inne listy.

Listy R są bardzo podobne do struktury danych mapy skrótów, ponieważ każdą wartość indeksu można powiązać z dowolnym obiektem. Oto prosty przykład listy zawierającej 3 różne klasy (w tym funkcję):

> complicated.list <- list("a"=1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
> lapply(complicated.list, class)
$a
[1] "integer"
$b
[1] "integer"
$c
[1] "matrix"
$d
[1] "function"

Biorąc pod uwagę, że ostatnim elementem jest funkcja wyszukiwania, mogę to tak nazwać:

> complicated.list[["d"]]()
[1] ".GlobalEnv" ...

Jako ostatni komentarz na ten temat: należy zauważyć, że a data.frameto tak naprawdę lista (z data.framedokumentacji):

Ramka danych to lista zmiennych o tej samej liczbie wierszy z unikalnymi nazwami wierszy, podana klasa „data.frame”

Właśnie dlatego kolumny w data.framemogą mieć różne typy danych, podczas gdy kolumny w macierzy nie. Jako przykład tutaj próbuję utworzyć macierz z liczbami i znakami:

> a <- 1:4
> class(a)
[1] "integer"
> b <- c("a","b","c","d")
> d <- cbind(a, b)
> d
 a   b  
[1,] "1" "a"
[2,] "2" "b"
[3,] "3" "c"
[4,] "4" "d"
> class(d[,1])
[1] "character"

Zwróć uwagę, że nie mogę zmienić typu danych w pierwszej kolumnie na numeryczny, ponieważ druga kolumna ma znaki:

> d[,1] <- as.numeric(d[,1])
> class(d[,1])
[1] "character"

4
To pomaga, dzięki. (Nawiasem mówiąc, twoja przykładowa „skomplikowana lista”, jak być może już wiesz, jest standardowym sposobem replikacji instrukcji „switch” w C ++, Javie itp. W językach, które jej nie mają; prawdopodobnie dobry sposób zrobić to w R, kiedy trzeba). +1
doug

8
Racja, chociaż switchw R jest przydatna funkcja, której można użyć do tego celu (patrz help(switch)).
Shane

63

Jeśli chodzi o twoje pytania, pozwól mi odpowiedzieć na nie w porządku i podać kilka przykładów:

1 ) Lista jest zwracana, jeśli i kiedy instrukcja return ją doda. Rozważać

 R> retList <- function() return(list(1,2,3,4)); class(retList())
 [1] "list"
 R> notList <- function() return(c(1,2,3,4)); class(notList())
 [1] "numeric"
 R> 

2 ) Nazwy po prostu nie są ustawione:

R> retList <- function() return(list(1,2,3,4)); names(retList())
NULL
R> 

3 ) Nie zwracają tego samego. Twój przykład daje

R> x <- list(1,2,3,4)
R> x[1]
[[1]]
[1] 1
R> x[[1]]
[1] 1

gdzie x[1]zwraca pierwszy element x- który jest taki sam jak x. Każdy skalar jest wektorem o długości jeden. Z drugiej strony x[[1]]zwraca pierwszy element listy.

4 ) Wreszcie, oba są różne, ponieważ tworzą odpowiednio listę zawierającą cztery skalary i listę z pojedynczym elementem (którym jest wektor czterech elementów).


1
Bardzo pomocny, dzięki. (W odpowiedzi nr 1 w odpowiedzi - zgadzam się, ale miałem na myśli wbudowane elementy takie jak „strsplit”, a nie funkcje tworzone przez użytkownika). W każdym razie +1 ode mnie.
doug

2
@doug O pozycji nr 1 Myślę, że jedynym sposobem jest sprawdzenie pomocy dla określonej funkcji, sekcja Value. Jak w ?strsplit: „Lista o tej samej długości co x”. Należy jednak wziąć pod uwagę, że funkcja może zwracać różne wartości zależne od argumentów (np. Sapply może zwrócić listę lub wektor).
Marek

34

Wystarczy wziąć podzbiór swoich pytań:

W tym artykule na temat indeksowania poruszono kwestię różnicy między []i [[]].

W skrócie [[]] wybiera pojedynczy element z listy i []zwraca listę wybranych elementów. W twoim przykładzie x = list(1, 2, 3, 4)'pozycja 1 jest pojedynczą liczbą całkowitą, ale x[[1]]zwraca pojedynczą 1 i x[1]zwraca listę z tylko jedną wartością.

> x = list(1, 2, 3, 4)
> x[1]
[[1]]
[1] 1

> x[[1]]
[1] 1

Nawiasem mówiąc, A = array( 11:16, c(2,3) ); A[5]czy 15 jest w płaskiej tablicy?!
den

13

Jednym z powodów, dla których listy działają tak, jak działają (uporządkowane), jest zaspokojenie zapotrzebowania na zamówiony kontener, który może zawierać dowolny typ w dowolnym węźle, czego nie robią wektory. Listy są ponownie używane do różnych celów w R, w tym do tworzenia podstawy a data.frame, która jest listą wektorów dowolnego typu (ale o tej samej długości).

Dlaczego te dwa wyrażenia nie zwracają tego samego wyniku?

x = list(1, 2, 3, 4); x2 = list(1:4)

Aby dodać do odpowiedzi @ Shane, jeśli chcesz uzyskać ten sam wynik, spróbuj:

x3 = as.list(1:4)

Który zmusza wektor 1:4do listy.


11

Dodajmy jeszcze jeden punkt:

R ma strukturę danych odpowiada dict Pythona w hashopakowaniu . Możesz przeczytać o tym w tym poście na blogu z Open Data Group . Oto prosty przykład:

> library(hash)
> h <- hash( keys=c('foo','bar','baz'), values=1:3 )
> h[c('foo','bar')]
<hash> containing 2 key-value pairs.
  bar : 2
  foo : 1

Pod względem użyteczności hashklasa jest bardzo podobna do listy. Ale wydajność jest lepsza w przypadku dużych zestawów danych.


1
Zdaję sobie sprawę z pakietu skrótu - jest on wymieniony w moim pierwotnym pytaniu jako odpowiedni serwer proxy dla tradycyjnego typu skrótu.
doug

Zauważ także, że użycie hash :: hash jest wątpliwym narzędziem w stosunku do środowisk mieszanych , rpubs.com/rpierce/hashBenchmarks .
russellpierce

9

Mówisz:

Po drugie, listy mogą być zwracane z funkcji, nawet jeśli nigdy nie przekazałeś Listu, gdy wywołałeś funkcję, i chociaż funkcja nie zawiera konstruktora List, np.

x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x)
# => 'list'

I myślę, że sugerujesz, że to jest problem (?). Jestem tutaj, aby ci powiedzieć, dlaczego to nie problem :-). Twój przykład jest nieco prosty, ponieważ kiedy dokonujesz podziału łańcucha, masz listę z elementami o długości 1 elementu, więc wiesz, że x[[1]]jest taki sam jak unlist(x)[1]. Ale co jeśli wynik strsplitzwracanych wyników o różnej długości w każdym pojemniku. Zwrócenie wektora (w porównaniu z listą) w ogóle nie wystarczy.

Na przykład:

stuff <- c("You, me, and dupree",  "You me, and dupree",
           "He ran away, but not very far, and not very fast")
x <- strsplit(stuff, ",")
xx <- unlist(strsplit(stuff, ","))

W pierwszym przypadku ( x: który zwraca listę) możesz powiedzieć, jaka była 2. „część” trzeciego ciągu, np x[[3]][2]. : Jak możesz zrobić to samo, skoro xxwyniki zostały „odkryte” ( unlist-ed)?


5
x = list(1, 2, 3, 4)
x2 = list(1:4)
all.equal(x,x2)

nie jest taki sam, ponieważ 1: 4 jest taki sam jak c (1,2,3,4). Jeśli chcesz, aby były takie same:

x = list(c(1,2,3,4))
x2 = list(1:4)
all.equal(x,x2)

4

To bardzo stare pytanie, ale myślę, że nowa odpowiedź może wnieść wartość dodaną, ponieważ moim zdaniem nikt nie zajął się bezpośrednio niektórymi obawami w PO.

Pomimo sugerowanych odpowiedzi, listobiekty w R nie są mapami skrótów. Jeśli chcesz zrobić równolegle z pythonem, listbardziej przypominasz, zgadnij, python list( tuplea właściwie s).

Lepiej jest opisać, w jaki sposób większość obiektów R jest przechowywanych wewnętrznie (typ C obiektu R to SEXP). Składają się zasadniczo z trzech części:

  • nagłówek, który deklaruje typ R obiektu, długość i niektóre inne metadane;
  • część danych, która jest standardową tablicą alokowaną na stercie C (ciągły blok pamięci);
  • atrybuty, które są nazwaną połączoną listą wskaźników do innych obiektów R (lub NULLjeśli obiekt nie ma atrybutów).

Z wewnętrznego punktu widzenia różnica między a listi numericwektorem jest na przykład niewielka . Wartości, które przechowują, są po prostu różne. Podzielmy dwa obiekty na opisany wcześniej paradygmat:

x <- runif(10)
y <- list(runif(10), runif(3))

Dla x:

  • Nagłówek powie, że typ to numeric( REALSXPpo stronie C), długość to 10 i inne rzeczy.
  • Część danych będzie tablicą zawierającą 10 doublewartości.
  • Atrybuty są NULL, ponieważ obiekt nie ma żadnych.

Dla y:

  • Nagłówek powie, że typ to list( VECSXPpo stronie C), długość to 2 i inne rzeczy.
  • Część danych będzie tablicą zawierającą 2 wskaźniki do dwóch typów SEXP, wskazując odpowiednio na wartość uzyskaną przez runif(10)i runif(3).
  • Atrybuty są NULLjak dla x.

Tak więc jedyną różnicą między numericwektorem a a listjest to, że numericczęść danych składa się z doublewartości, podczas gdy dla listczęści danych jest tablica wskaźników do innych obiektów R.

Co dzieje się z imionami? Cóż, nazwy to tylko niektóre atrybuty, które można przypisać do obiektu. Zobaczmy obiekt poniżej:

z <- list(a=1:3, b=LETTERS)
  • Nagłówek powie, że typ to list( VECSXPpo stronie C), długość to 2 i inne rzeczy.
  • Część danych będzie tablicą zawierającą 2 wskaźniki do dwóch typów SEXP, wskazując odpowiednio na wartość uzyskaną przez 1:3i LETTERS.
  • Atrybuty są teraz obecne i są namesskładnikiem, który jest obiektem characterR o wartości c("a","b").

Z poziomu R można odzyskać atrybuty obiektu za pomocą attributesfunkcji.

Kluczowa wartość typowa dla mapy skrótu w R jest tylko iluzją. Kiedy powiesz:

z[["a"]]

Oto co się dzieje:

  • [[funkcja podzbiór nazywa;
  • argument funkcji ( "a") jest typu character, więc metoda ma poszukać takiej wartości z namesatrybutu (jeśli występuje) obiektu z;
  • jeśli namesatrybutu nie ma, NULLjest zwracany;
  • jeśli jest obecny, "a"wartość jest w nim przeszukiwana. Jeśli "a"nie jest nazwą obiektu, NULLjest zwracany;
  • jeśli jest obecny, pozycja jest określana (1 w przykładzie). Tak więc zwracany jest pierwszy element listy, czyli odpowiednik z[[1]].

Wyszukiwanie klucz-wartość jest raczej pośrednie i zawsze ma charakter pozycyjny. Warto również pamiętać:

  • w mapach skrótów jedynym ograniczeniem, jakie musi mieć klucz, jest to, że musi on być mieszalny . namesin R muszą być łańcuchami ( characterwektorami);
  • w mapach skrótów nie można mieć dwóch identycznych kluczy. W R możesz przypisać namesobiektowi z powtarzanymi wartościami. Na przykład:

    names(y) <- c("same", "same")

    jest całkowicie poprawny w R. Gdy spróbujesz, y[["same"]]pierwsza wartość jest pobierana. Powinieneś wiedzieć, dlaczego w tym momencie.

Podsumowując, możliwość nadania obiektowi dowolnych atrybutów daje wygląd czegoś innego niż zewnętrzny punkt widzenia. Ale R listnie są w żaden sposób mapami skrótu.


2

Odnośnie wektorów i koncepcji skrótu / tablicy z innych języków:

  1. Wektory to atomy R. Np. rpois(1e4,5)(5 liczb losowych), numeric(55)(wektor zerowy o długości 55 nad podwójnymi) i character(12)(12 pustych łańcuchów) wszystkie są „podstawowe”.

  2. Listy lub wektory mogą mieć names.

    > n = numeric(10)
    > n
     [1] 0 0 0 0 0 0 0 0 0 0
    > names(n)
    NULL
    > names(n) = LETTERS[1:10]
    > n
    A B C D E F G H I J 
    0 0 0 0 0 0 0 0 0 0
  3. Wektory wymagają, aby wszystko było tego samego typu danych. Patrz na to:

    > i = integer(5)
    > v = c(n,i)
    > v
    A B C D E F G H I J           
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    > class(v)
    [1] "numeric"
    > i = complex(5)
    > v = c(n,i)
    > class(v)
    [1] "complex"
    > v
       A    B    C    D    E    F    G    H    I    J                          
    0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i
  4. Listy mogą zawierać różne typy danych, co widać w innych odpowiedziach i samym pytaniu PO.

Widziałem języki (ruby, javascript), w których „tablice” mogą zawierać zmienne typy danych, ale na przykład w C ++ „tablice” muszą być tego samego typu. Wierzę, że jest to kwestia prędkości / wydajności: jeśli masz numeric(1e6), znasz jego rozmiar i lokalizację każdego elementu a priori ; jeśli rzecz może zawierać "Flying Purple People Eaters"jakiś nieznany kawałek, wtedy trzeba przeanalizować różne rzeczy, aby poznać podstawowe fakty.

Niektóre standardowe operacje R mają również większy sens, gdy typ jest gwarantowany. Na przykład cumsum(1:9)ma sens, a cumsum(list(1,2,3,4,5,'a',6,7,8,9))nie ma, bez zagwarantowania, że ​​typ będzie podwójny.


Co do twojego drugiego pytania:

Listy mogą być zwracane z funkcji, nawet jeśli nigdy nie przeszedłeś do Listy, gdy wywołałeś funkcję

Funkcje zwracają różne typy danych niż cały czas są wprowadzane. plotzwraca wykres, nawet jeśli nie pobiera wykresu jako danych wejściowych. Argzwraca a, numericmimo że zaakceptował complex. Itp.

(A jeśli chodzi o strsplit: kod źródłowy jest tutaj .)


2

Chociaż to dość stare pytanie, muszę powiedzieć, że dotyka dokładnie wiedzy, której brakowało mi podczas pierwszych kroków w R - tj. Jak wyrażać dane w mojej dłoni jako obiekt w R lub jak wybierać z istniejących obiektów. Nowicjuszowi R nie jest łatwo myśleć „w pudełku R.” od samego początku.

Więc sam zacząłem używać kul, które pomogły mi bardzo dużo dowiedzieć się, jakiego obiektu użyć do jakich danych, i po prostu wyobrazić sobie użycie w rzeczywistym świecie.

Chociaż nie udzielam dokładnych odpowiedzi na pytanie, krótki tekst poniżej może pomóc czytelnikowi, który właśnie zaczął od R i zadaje podobne pytania.

  • Wektor atomowy ... Nazywałem to „sekwencją” dla siebie, bez kierunku, po prostu sekwencją tego samego typu. [podzbiory.
  • Wektor ... sekwencja z jednym kierunkiem z 2D, [podzbiorów.
  • Matryca ... wiązka wektorów o tej samej długości tworzących rzędy lub kolumny, [podzbiory według rzędów i kolumn lub według sekwencji.
  • Tablice ... warstwowe matryce tworzące 3D
  • Ramka danych ... tabela 2D jak w programie Excel, w której mogę sortować, dodawać lub usuwać wiersze lub kolumny lub tworzyć arit. operacje z nimi, dopiero po pewnym czasie naprawdę zrozumiałem, że ramka danych jest sprytną implementacją tego, listgdzie mogę podzbiór za [pomocą wierszy i kolumn, ale nawet za pomocą [[.
  • Lista ... aby sobie pomóc, pomyślałem o liście od momentu, w tree structurektórym [i]wybiera i zwraca całe gałęzie oraz [[i]]zwraca element z gałęzi. A ponieważ tak jest tree like structure, możesz nawet użyć index sequencedo rozwiązania każdego pojedynczego liścia na bardzo złożonym listza pomocą jego [[index_vector]]. Listy mogą być proste lub bardzo złożone i mogą łączyć różne typy obiektów w jeden.

Więc listsmożesz skończyć z większą liczbą sposobów wyboru w leafzależności od sytuacji, jak w poniższym przykładzie.

l <- list("aaa",5,list(1:3),LETTERS[1:4],matrix(1:9,3,3))
l[[c(5,4)]] # selects 4 from matrix using [[index_vector]] in list
l[[5]][4] # selects 4 from matrix using sequential index in matrix
l[[5]][1,2] # selects 4 from matrix using row and column in matrix

Ten sposób myślenia bardzo mi pomógł.


1

Jeśli to pomaga, zwykle wyobrażam sobie „listy” w R jako „rekordy” w innych językach sprzed OO:

  • nie przyjmują żadnych założeń dotyczących nadrzędnego typu (a raczej dostępny jest typ wszystkich możliwych rekordów dowolnej arity i nazw pól).
  • ich pola mogą być anonimowe (wtedy uzyskuje się do nich dostęp w ścisłej kolejności definicji).

Nazwa „rekord” koliduje ze standardowym znaczeniem „rekordy” (aka wiersze) w języku bazy danych i być może dlatego ich nazwa sugeruje się: jako listy (pól).


1

Dlaczego te dwa różne podmioty, [ ]oraz [[ ]], zwraca ten sam wynik?

x = list(1, 2, 3, 4)
  1. [ ]zapewnia operację ustawienia podrzędnego. Zasadniczo podzestaw dowolnego obiektu będzie miał ten sam typ, co obiekt oryginalny. Dlatego x[1] zapewnia listę. Podobnie x[1:2]jest podzbiorem oryginalnej listy, dlatego jest listą. Dawny.

    x[1:2]
    
    [[1]] [1] 1
    
    [[2]] [1] 2
  2. [[ ]]służy do wyodrębnienia elementu z listy. x[[1]]jest poprawny i wypakuj pierwszy element z listy. x[[1:2]]nie jest poprawny, ponieważ [[ ]] nie zapewnia ustawienia podrzędnego, takiego jak [ ].

     x[[2]] [1] 2 
    
    > x[[2:3]] Error in x[[2:3]] : subscript out of bounds
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.