如何通过自定义功能对列表进行排序,并丢弃重复项?

时间:2019-11-08 00:04:54

标签: r sorting

我有此列表:

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)
)

我想通过每个元素的“值”字段对其进行排序,并丢弃重复项,以使结果列表中没有两个元素具有相同的“值”字段(当出现平局时被选择的元素无关紧要)。

sortunique不适用于复杂的列表,并且不允许自定义排序。如何达到预期的效果?

3 个答案:

答案 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

但是,由于我们要删除重复项,因此不可能如此简单。 uniquethresholds上不起作用,如果我们将其应用于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所示,我们可以将自定义sortunique函数应用于任何列表(或其他对象)。

首先,需要添加“类别”属性:

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))

(相似的答案和更多信息herehere

答案 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