1
votes

Suppression des listes imbriquées de longueur 0

J'ai une liste de listes de listes dans R. Je veux supprimer celles qui sont de longueur zéro.

Ce que j'ai essayé jusqu'à présent est:

test <- list("Section 1" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")),
         "Section 2" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")))

Voici quelques exemples de données (édités):

for (i in 1:length(test)) {
  keep <- rep(T, length(test))
  for (j in 1:length(test[[i]])) {
    if (length(test[[i]][[j]]) == 0) {
      keep[[j]] <- F
    }
  }
  test2[i] <- test2[i][keep]
}

Je voudrais un moyen de supprimer la liste "A" à la fois dans la section 1 et la section 2 puisque les deux sont de longueur 0

r

4 commentaires

Je suppose qu'il s'agit d'un double du message lié. Je ne peux pas être sûr à 100% car vous ne fournissez pas d'exemples de données (les captures d'écran sont toujours une mauvaise idée pour partager des données). Si la ou les solutions de la cible dupe ne résolvent pas votre problème, veuillez clarifier votre message, inclure des exemples de données et je serai heureux de rouvrir.


@MauritsEvers j'ai ajouté quelques exemples de données, merci


Filter (function (x) length (x)> 0, test) fonctionne pour les exemples de données que vous donnez.


@MauritsEvers, pas besoin de la fonction anonyme: Filtre (longueur, test)


3 Réponses :


0
votes

Revendiquer qu'il s'agit d'un doublon nécessite la connaissance supplémentaire que les listes contenant uniquement des éléments NULL ont une longueur de 0. Nécessite également de supposer que NULL et list () sont équivalents. Ni l'un ni l'autre ne sont nécessairement évidents, bien que tester cette proposition avec sapply (list (a = NULL), length) montre que le premier est le cas. Le second n'apparaît cependant pas comme le cas. Test: identique (NULL, list ()) renvoie FALSE, tout comme identique (list (NULL), list ()) et is.null (list ( )) .

La réponse de Maurits Evers devrait réussir. Cela réussira également:

 test <- test[ sapply(test, length) >0] # `sapply will return a logical vector

> test
$B
$B$`1x1`
[1] "23"

$B$`1x2`
[1] "24"


$C
$C$`2x1`
[1] "78"


2 commentaires

test [longueurs (test)> 0]


Bon. J'aurais peut-être su à un moment qu'il existait une version vectorisée de length , mais si c'était le cas, je l'avais oublié.



1
votes

Juste pour conclure, et selon mon commentaire précédent, vous pouvez faire

test <- list("Section 1" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")), "Section 2" = list("A" = list(), "B" = list("1x1" = "23", "1x2" = "24"), C = list("2x1" = "78")))
lapply(test, function(x) Filter(length, x))
#$`Section 1`
#$`Section 1`$B
#$`Section 1`$B$`1x1`
#[1] "23"
#
#$`Section 1`$B$`1x2`
#[1] "24"
#
#
#$`Section 1`$C
#$`Section 1`$C$`2x1`
#[1] "78"
#
#
#
#$`Section 2`
#$`Section 2`$B
#$`Section 2`$B$`1x1`
#[1] "23"
#
#$`Section 2`$B$`1x2`
#[1] "24"
#
#
#$`Section 2`$C
#$`Section 2`$C$`2x1`
#[1] "78"

ou plus court encore (merci @Parfait)

Filter(length, test)

Pour une list

Filter(function(x) length(x) > 0, test)
#$B
#$B$`1x1`
#[1] "23"
#
#$B$`1x2`
#[1] "24"
#
#
#$C
#$C$`2x1`
#[1] "78"

imbriquée


5 commentaires

cela peut-il être utilisé dans une boucle for pour obtenir des listes vierges de chaque section? Données EX: test <- liste ("Section 1" = liste ("A" = liste (), "B" = liste ("1x1" = "23", "1x2" = "24"), C = liste ( "2x1" = "78")), "Section 2" = liste ("A" = liste (), "B" = liste ("1x1" = "23", "1x2" = "24"), C = liste ("2x1" = "78")))


Pas besoin d'un pour boucle explicite @ user10256905; enveloppez simplement la déclaration Filter dans lapply , voir ma modification.


cela nécessite que toutes les listes vides soient au même niveau, en ce que si vous aviez test $ s = list () la fonction lapply ne pourra pas capturer cela


@Onyambu Oui en effet. C'est pour l'exemple de données fourni par OP dans le commentaire ci-dessus.


Je pense toujours qu'il s'agit d'un article en double d'une manière ou d'une autre; par exemple. pour la suppression récursive des éléments NULL, voir Supprimer les éléments NULL de la liste des listes



1
votes

Vous pouvez simplement écrire votre propre fonction:

check = function(x){
  m = lengths(x)>0
  if(is.list(x[m])) lapply(x[m],check) else x
 }

check(test)
$`Section 1`
$`Section 1`$`B`
$`Section 1`$`B`$`1x1`
[1] "23"

$`Section 1`$`B`$`1x2`
[1] "24"


$`Section 1`$C
$`Section 1`$C$`2x1`
[1] "78"



$`Section 2`
$`Section 2`$`B`
$`Section 2`$`B`$`1x1`
[1] "23"

$`Section 2`$`B`$`1x2`
[1] "24"


$`Section 2`$C
$`Section 2`$C$`2x1`
[1] "78"


0 commentaires