glenn jackman
glenn jackman

Reputation: 246837

Using `lmap` to filter list of strings

Suppose I want to get all the 5-letter words from a list.

set words {apple banana grape pear peach}
lmap word $words {if {[string length $word] == 5} {expr {"$word"}} else continue}
# ==> apple grape peach

I'm not happy with the quoting mess of expr {"$word"}. I was hoping this would work:

lmap word $words {if {[string length $word] == 5} {return $word} else continue}
# ==> apple

What's an elegant way to "return" a string from the lmap body?

Upvotes: 2

Views: 2886

Answers (2)

Peter Lewerin
Peter Lewerin

Reputation: 13252

I usually use set:

lmap word $words {if {[string length $word] == 5} {set word} else continue}

or sometimes (if I'm sure expr won't reinterpret the value in word):

lmap word $words {expr {[string length $word] == 5 ? $word : [continue]}}

There's this too, of course:

lsearch -regexp -all -inline $words ^.{5}$

Documentation: continue, expr, if, lmap, lsearch, set, string

Upvotes: 2

Donal Fellows
Donal Fellows

Reputation: 137587

The main choices are to use set or to use string cat (assuming you're up to date). I've split the examples below over multiple lines for clarity:

lmap word $words {
    if {[string length $word] != 5} {
        continue
    };
    set word
}
lmap word $words {
    if {[string length $word] == 5} {
        # Requires 8.6.3 or later
        string cat $word
    } else {
        continue
    }
}

Upvotes: 5

Related Questions