我有此列表:
thresholds <- list(
list(color="red", value=100),
list(color="blue", value=50),
list(color="orange", value=100),
list(color="green", value=1),
list(color="orange", value=50)
)
我想通过每个元素的“值”字段对其进行排序,并丢弃重复项,以使结果列表中没有两个元素具有相同的“值”字段(当出现平局时被选择的元素无关紧要)。
sort
和unique
不适用于复杂的列表,并且不允许自定义排序。如何达到预期的效果?
答案 0 :(得分:7)
首先,在这种情况下,要订购的实际向量为:
values <- sapply(thresholds, function (t) t$value)
# values == c(100, 50, 100, 1, 50)
您可以根据需要调整sapply
中的函数(例如,根据要按数字顺序还是字母顺序进行排序等)。
从这一点出发,如果我们要保留重复项,答案将是:
thresholds[order(values)]
order
为“值”中的每个元素返回其排名,即如果对向量进行了排序,则返回其位置。这里order(values)
是4 2 5 1 3
。然后,thresholds[order(values)]
返回由这些索引标识的thresholds
的元素,从而产生1 50 50 100 100
。
但是,由于我们要删除重复项,因此不可能如此简单。 unique
在thresholds
上不起作用,如果我们将其应用于values
,它将丢失与原始列表中索引的对应关系。
解决方案是使用另一个功能,即duplicated
。当应用于向量时,duplicated
返回一个布尔向量,指示每个元素是否早已存在于向量中。例如,duplicated(values)
将返回FALSE FALSE TRUE FALSE TRUE
。此向量是我们在此处需要的重复元素的过滤器。
因此,解决方案是:
ordering <- order(values)
nodups <- ordering[!duplicated(values)]
thresholds[nodups]
或单线:
thresholds[order(values)[!duplicated(values)]]
答案 1 :(得分:2)
为完整性起见,为问题的“自定义排序” /“自定义唯一”部分添加了另一种选择。通过为某些函数定义方法(如?xtfrm
所示,我们可以将自定义sort
和unique
函数应用于任何列表(或其他对象)。
首先,需要添加“类别”属性:
class(thresholds) = "thresholds"
然后,定义必要的自定义函数:
"==.thresholds" = function(x, y) return(x[[1]][["value"]] == y[[1]][["value"]])
">.thresholds" = function(x, y) return(x[[1]][["value"]] > y[[1]][["value"]])
"[.thresholds" = function(x, i) return(structure(.subset(x, i), class = class(x)))
is.na.thresholds = function(x) return(is.na(x[[1]][["value"]]))
现在,我们可以应用sort
:
sort(thresholds)
最后,添加一个自定义unique
函数:
duplicated.thresholds = function(x, ...) return(duplicated(sapply(x, function(elt) elt[["value"]])))
unique.thresholds = function(x, ...) return(x[!duplicated((x))])
并且:
sort(unique(thresholds))
答案 2 :(得分:0)
如果您喜欢花括号,可以这样做:
x.value
在最后的括号中包括自定义排序。
thresholds[{order(v <- unlist(Map(`[`, thresholds, 2)))}[!duplicated(v)]]
# [[1]]
# [[1]]$color
# [1] "green"
#
# [[1]]$value
# [1] 1
#
#
# [[2]]
# [[2]]$color
# [1] "blue"
#
# [[2]]$value
# [1] 50
#
#
# [[3]]
# [[3]]$color
# [1] "red"
#
# [[3]]$value
# [1] 100