Remove last comma from a bash for loop generated string

One option is to stick with bash

arr=(a b c)
x=$(IFS=,;printf  "%s" "${arr[*]}")
echo "$x"
a,b,c

Alternately

arr=(a b c)
printf -v x "%s," "${arr[@]}"
x=${x%,}
echo "$x"
a,b,c

With the second option, you can set the separator to ,(comma followed by space) instead of , alone

printf -v x "%s, " "${arr[@]}"
x=${x%, }
echo "$x"
a, b, c

The issue was that, by default, echo adds a new line each time it is called and sed was operating on those new lines. You couldn't see that because, when bash processes $(...), those new lines are converted to spaces. So, to fix the problem while making the smallest change to your approach:

$ x=$(for i in a b c; do echo -n "${i}",; done| sed 's/,$//') ; echo $x
a,b,c

The option -n tells echo not to add new lines.

If you want spaces between the items, they are easily added:

$ x=$(for i in a b c; do echo -n "${i}, " ; done| sed 's/, $//') ;echo $x
a, b, c

another useful technique for this is paste -s:

$ arr=(a b c)
$ printf "%s\n" "${arr[@]}" | paste -sd,
a,b,c

(note that the paste -sd, here is a very general "turn this set of newline-separated items into a comma-separated list" operation)