We are already halfway there. We can compare the result against an integer, in this case the amount of columns we want.
dfcols == 4
#> df1 df2 df3
#> FALSE TRUE FALSE
And use this for logical subsetting of the original list.
selection <- toy_list[dfcols == 4]
selection
#> $df2
#> a b c d
#> 1 1 3 5 7
#> 2 2 4 6 8
Note that this will return a list as well and will contain all entries with four columns. Of course you can extract the individual items from that list as well.
selection[[1]]
#> a b c d
#> 1 1 3 5 7
#> 2 2 4 6 8
Note, that instead of lapply you could also use purrr::map in the same way if you want a tidyverse solution.
library("purrr")
selection <- toy_list %>% keep(~ ncol(.x) == 4)
selection
#> $df2
#> a b c d
#> 1 1 3 5 7
#> 2 2 4 6 8
Note that this returns a list so, as above you need to select individual elements separately as well.
selection[[1]]
#> a b c d
#> 1 1 3 5 7
#> 2 2 4 6 8
If you want to keep the information on the amount of columns in each data.frame around you can obtain it in a call similar to the lapply above, but with map.