2015-01-12 4 views
17

Я хотел бы проверить, содержат ли два вектора одни и те же элементы, даже если они не упорядочены одинаково. Например, функция (назовем его SameElements) должны удовлетворять следующим критериям:Проверьте, содержат ли два вектора одинаковые (неупорядоченные) элементы в R

SameElements(c(1, 2, 3), c(1, 2, 3)) # TRUE 
SameElements(c(1, 2, 3), c(3, 2, 1)) # TRUE 
SameElements(c(1, 2, 1), c(1, 2)) # FALSE 
SameElements(c(1, 1, 2, 3), c(3, 2, 1)) # FALSE 

Edit 1: указано, что функция должна возвращать F, когда векторы содержат одни и те же элементы, но с разными частотами.

Редактировать 2: Убрать вопрос, чтобы опустить исходный ответ, так как это сейчас в моем фактическом ответе.

+0

Как насчет 'всех (в% в% б)'. Это в основном отвечает на вопрос * Все ли элементы 'a' содержатся в векторе' b'? * Если значения уникальны, вы также можете использовать что-то вроде 'anyNA (match (a, b))' –

+0

А хороший вызов , извините, здесь было неясно. Я ищу F в этом сценарии (вопрос изменен для ясности). –

ответ

8

Вместо чистого альтернативы, здесь известное решение:

SameElements <- function(a, b) return(identical(sort(a), sort(b))) 
SameElements(c(1, 2, 3), c(1, 3, 2)) # TRUE 
SameElements(c(1, 2, 3), c(1, 1, 3, 2)) # FALSE 

Edit: identical вместо all.equal(...) == T по предложению nrussell в.

+1

Тип расщепляющих волосков, но функция F <- (a, b) идентична (sort (a), sort (b)) 'сохранит вам 3 нажатия клавиш (' == T') из функции 'SameElements' выше - опрятный вопрос, хотя +1. – nrussell

+0

Спасибо @nrussell, обновлено –

30

Я думаю, что вы можете использовать setequal(a,b)

Обновлено обновлениеsetequal проверки, если два вектора состоят из одних и тех же элементов, но он не проверяет, если эти элементы имеют одни и те же вхождения в каждом векторе.

+2

setequal для меня новичок и выглядит аккуратно. +1 –

+1

Это в основном просто '% in%' :) –

+1

Ya figured. Также он должен делать что-то дополнительное, так как оно медленнее. Но с точки зрения «чистой альтернативы» она выигрывает. трудно получить чище. :) –

3

Возможно, вас заинтересует пакет «Сравнить». Этот ответ демонстрирует функцию compare(), но для вашего случая вы можете отлично справиться с compareIgnoreOrder() (что почти совпадает с названием вашего вопроса).

Существует несколько аргументов, которые могут быть добавлены как преобразования, которые должны быть разрешены при попытке сравнить элементы. В приведенных ниже примерах (чтобы сохранить некоторую типизацию) я попросил функцию разрешить все преобразования (allowAll = TRUE), за исключением изменения длины вектора (shorten = FALSE).

library(compare) 
compare(A1, A2, allowAll = TRUE, shorten = FALSE) 
# TRUE 
compare(A1, A3, allowAll = TRUE, shorten = FALSE) 
# TRUE 
# sorted 
compare(A1, A4, allowAll = TRUE, shorten = FALSE) 
# FALSE 
# sorted 
compare(B1, B2, allowAll = TRUE, shorten = FALSE) 
# FALSE 
# sorted 
compare(B1, A4, allowAll = TRUE, shorten = FALSE) 
# FALSE 
# sorted 
compare(A3f, A1, allowAll = TRUE, shorten = FALSE) 
# TRUE 
# coerced from <numeric> to <factor> 
# sorted 

Образец данных:

A1 <- c(1, 2, 3); A2 <- c(1, 2, 3) 
A3 <- c(3, 2, 1); A4 <- c(1, 1, 2, 3) 
B1 <- c(1, 2, 1); B2 <- c(1, 2) 
A3f <- factor(A3) 
0

Вот мое решение:

SameElements <- function (a,b){ 
    l <- Map(table,list(a, b)) # Compute frequencies - returns ordered table 
    Reduce(identical,l) # Check if frequencies are the same for all input vectors 
} 

SameElements(c(1, 2, 3), c(1, 2, 3)) # TRUE 
SameElements(c(1, 2, 3), c(3, 2, 1)) # TRUE 
SameElements(c(1, 2, 1), c(1, 2)) # FALSE 
SameElements(c(1, 1, 2, 3), c(3, 2, 1)) # FALSE 

Как вы можете видеть, что это работает для любого числа входных векторов до тех пор, как вы их все в список.

Один лайнер:

Reduce(identical,Map(table,listOfVectors)) 
Смежные вопросы