It's a question of which you prefer: declarative or imperative. Having that in mind, and knowing that "readability" is a tricky concept, here is an example in LiveScript:
# utility, normally wouldn't be here
map2 = (f, xs, ys) ->
map (apply f, _), (zip xs, ys)
startsWith = (prefix, str) ->
map2 (==), prefix, str |> and-list
endsWith = (suffix, str) ->
revStr = unchars << reverse << chars
startsWith (revStr suffix), (revStr str)
"<<" is function composition, "|>" is a "pipe" or "reverse application order operator", "_" is partial application. "map", "zip" and "apply" functions are standard and have expected semantics, "chars" transforms a string into an array of chars and "unchars" does the opposite (and they all come from prelude-ls library).
This code is both shorter and easier to read (to me, at least) than equivalent for loops and it also composes better. The details of iteration are irrelevant here and so are abstracted, which means they can be trivially changed.
Of course, for "map" to be this useful it needs to be supported by many functionally oriented language constructs. It's also not the best example for anything, it's just a piece of code I wrote in a style I like, in a language I use.