You can get the amount of columns in a data.frame using ncol.
So, in your case calling ncol(toy_list$df1) will return 3.
Of course, you want to apply this to many items in a list, making it a great job for the apply family, in this case for lapply.
dfcols <- lapply(toy_list, ncol)
dfcols
#> $df1
#> [1] 3
#>
#> $df2
#> [1] 4
#>
#> $df3
#> [1] 1
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.