Ссылаясь на этот пример:
z <- list(a = 1, b = "c", c = 1:3)
names(z)
# change just the name of the third element.
names(z)[3] <- "c2"
z
Документация по именам говорит: «см. примеры. Это работает, потому что выражение там оценивается как z <- "names<-"(z, "[<-"(names(z), 3, "c2")) ."
О чем эта последняя строка кода? Он не соответствует синтаксису R, с которым я знаком, поэтому я даже не могу понять, как его читать. Во всяком случае, это кажется более сложным, чем пример, который он пытается объяснить. Как мне это прочитать?
@akrun Я многое понял, но "names<-"
было слишком далеко для меня.
Если набрать в консоли. вы получите ``names<-` function (x, value) .Primitive("names<-")# name# function (x) .Primitive("names")`
Есть некоторые функции, которые имеют аналогичные аналоги присваивания, например. substring
Просто помните, что часто, когда у вас есть funcname(leftside) <- rightside
, это на самом деле звонок `funcname<-`(leftside, rightside)
Я использовал обратные кавычки вместо двойных кавычек, поскольку двойные кавычки могут быть оценены как строка, а обратные кавычки оцениваются как есть.
@thelatemail Я нашел иначе stackoverflow.com/q/65395373/10319707
Эта часть документации действительно написана плохо, я не виню вас за то, что вы запутались.
Вот краткий ответ, скажем, у вас есть вектор z = c(a = 1, b = 2, c = 3)
, тогда следующие эквивалентны:
names(z)[3] <- "c2"
и
z <- "names<-"(z, "[<-"(names(z), 3, "c2"))
Это все, что говорится в документации.
Вот более длинный ответ: в R вы, вероятно, знакомы с основным синтаксисом функции, поэтому, допустим, у вас есть foo = function(x,y) x + y
, тогда вы, вероятно, привыкли вызывать foo(1, 2)
. Возможно, вы также видели «инфиксные» операторы, такие как +
, так что вы, вероятно, знакомы с 1 + 2
. Однако внутри это на самом деле читается как "+"(1,2)
(попробуйте, это сработает). То же самое наблюдается с функциями присваивания и извлечения, например x[1]
(для некоторого вектора x
) или как в этом примере names(z)[3] <-
, где <-
— оператор присваивания.
Чтобы сделать этот пример еще более сложным, на самом деле используются два отдельных инфиксных оператора! Есть names<-
и есть [<-
, первый используется для установки имени вектора, а второй используется для установки значения в векторе после первого извлечения вектора (я знаю, что здесь происходит многое).
Итак, разберем, что эта строка говорит в более знакомом коде R:
z <- "names<-"(z, "[<-"(names(z), 3, "c2"))
z
: исходный векторy = names(z)
: Вектор символов - имена z.y[3]<-"c2"
: извлеките третий элемент из y
и присвойте ему значение «c2». Теперь мы в "[<-"(names(z), 3, "c2")
.names(z)<-y
: Установите имена z
как y. Теперь мы в "names<-"(z, "[<-"(names(z), 3, "c2"))
.Просто чтобы еще больше запутать ситуацию, "names<-"
не сохраняет новый именованный вектор, а просто устанавливает новые имена. Вот почему z <- "names<-"...
требуется в конце, чтобы перезаписать исходную переменную с новым именем.
И показываю это с помощью R-кода:
> z = c(a = 1, b = 2, c = 3)
> print(z)
a b c
1 2 3
> names = names(z)
> names[3] = "c2"
> names(z) = names
> print(z)
a b c2
1 2 3
Если "[<-"
— это присваивание и извлечение, то почему "[<-"(names(z), 3, "c2")
не означает «взять третий элемент имен (z) и присвоить ему «c2»?»
Используя переменные в качестве примера: x[y] <- z
эквивалентно "[<-"(x,y,z)
. Первый аргумент — это вектор, который нужно присвоить, второй — индекс элемента, который нужно изменить, третий — значение замены. Итак, здесь мы говорим: из названий z
замените третье значение на «c2». Протестируйте это с помощью: '[<-'(letters, 1, "d")
Я думаю, вы пропустили шаг 5: последний z <-
бит. Вероятно, также стоит отметить, что "[<-"(names(z), 3, "c2")
возвращает все имена z.
Я улучшил пример (надеюсь)
Итак, что нужно знать о names(z)<-
, так это то, что на самом деле он не просто берет вектор и меняет его имена, он делает следующее: i) получает имена; ii) изменить имена; iii) перезаписать исходную переменную новыми именами. Это очень тонкий момент в R-кодировании, и единственный способ понять его — протестировать, просто запустите следующее, и вы поймете, что я имею в виду: z = c(a = 1, b = 2, c = 3); "names<-"(z, "[<-"(names(z), 3, "c2"))
. Вы должны увидеть, что "names<-"
на самом деле не сохраняет результат, поэтому вам нужно перезаписать z
Я согласен, я отредактировал ответ после того, как написал комментарий. Рад, что на ваш вопрос теперь дан ответ. А также спасибо за вызов объяснить это.
Меня все еще не совсем устраивает это. Предположение о том, что "names<-"(x,y)
не идентично names(x)<-y
, похоже, противоречит тому, как должны работать операторы инфликса.
Странно, наверное, я не думал об этом раньше. Это справедливо для всех операторов присваивания в R, например: x = 1:2; "[<-"(x,1,3)
. Я предполагаю, что это связано с семантикой копирования при изменении?
Я задам новый вопрос об этом.
names<-
— это другая функция, которая выполняет задание