views:

222

answers:

2

OK, I've got two named lists, one is "expected" and one is "observed". They may be complex in structure, with arbitrary data types. I want to get a new list containing just those elements of the observed list that are different from what's in the expected list. Here's an example:

Lexp <- list(a=1, b="two", c=list(3, "four"))
Lobs <- list(a=1, c=list(3, "four"), b="ni")
Lwant <- list(b="ni")

Lwant is what I want the result to be. I tried this:

> setdiff(Lobs, Lexp)
[[1]]
[1] "ni"

Nope, that loses the name, and I don't think setdiff pays attention to the names. Order clearly doesn't matter here, and I don't want a=1 to match with b=1.

Not sure what a good approach is... Something that loops over a list of names(Lobs)? Sounds clumsy and non-R-like, although workable... Got any elegant ideas?

A: 

OK, I found one slightly obtuse answer, using the plyr package:

> Lobs[laply(names(Lobs), function(x) !identical(Lobs[[x]], Lexp[[x]]))]
$b
[1] "ni"

So, it takes the names of the array from the observed function, uses double-bracket indexing and the identical() function to compare the sub-lists, then uses the binary array that results from laply() to index into the original observed function.

Anyone got a better/cleaner/sexier/faster way?

Harlan
You don't need plyr: Lobs[sapply(names(Lobs), function(x) !identical(Lobs[[x]], Lexp[[x]]))]
Marek
+3  A: 

At least in this case

Lobs[!(Lobs %in% Lexp)]

gives you what you want.

Peter
I was just using the %in% function yesterday for debugging and was about the recommend that.
JD Long