Last occurance of a character in a String

810 views
Skip to first unread message

noodle

unread,
May 28, 2013, 10:25:26 PM5/28/13
to elixir-l...@googlegroups.com
Hi,
 
I'm super uber new with Elixir. I read the document for string, but I still can't find a way to do it. I'm trying to find the last occurrence of a character in a String something like String.indexOf() but I can't seem to find a way to do it without splitting the string by the spaces and build them back together.
 
For example, if I have this string:
text = "My dog is cute."
 
Is there a way I can say text.last_index(' ') and it will return 9?
 
Thanks.

Alexei Sholik

unread,
May 29, 2013, 4:19:33 AM5/29/13
to elixir-l...@googlegroups.com
I don't think there is a builtin way, but it's doable.

Enum.reduce String.codepoints(text), {0, -1}, fn(str, { i, last_occurrence })->
  if str == " " do
    last_occurrence = i
  end
  { i + 1, last_occurrence }
end

You have some choices here:
* String.codepoints and String.graphemes may return different results depending on the string content (if it's heavy with non-ASCII characters). You could also use binary_to_list to get just a list of bytes.
* you could reverse the list of codepoints/bytes first and then use Enum.find_index.

We also have a proposal for String.find function https://github.com/elixir-lang/elixir/issues/1119. Presumably, it could accept an option to make is search backwards. You would then be able to subtract the returned value from the string length.


--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Best regards
Alexei Sholik

José Valim

unread,
May 29, 2013, 4:24:03 AM5/29/13
to elixir-l...@googlegroups.com
There is String.last.


José Valim
Skype: jv.ptec
Founder and Lead Developer

Yvan Godin

unread,
May 30, 2013, 8:24:56 AM5/30/13
to elixir-l...@googlegroups.com
Hi 
only for the fun 
 x = "azerty qsdf wxcv"
 length(String.codepoints x) - (length(Enum.take_while Enum.reverse((String.codepoints x)) , fn(x) -> x != " " end))
 12

Yvan

Alexei Sholik

unread,
May 30, 2013, 8:42:26 AM5/30/13
to elixir-l...@googlegroups.com
Yvan, taking a length of a list is better avoided in any practical usage, it's O(n). Treat lists like arrays in C: you don't know their size unless you keep it in a variable somewhere ;)


--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Yvan Godin

unread,
May 30, 2013, 9:36:13 AM5/30/13
to elixir-l...@googlegroups.com
OK I better understand your solution now
thank's 

Yvan Godin

unread,
May 30, 2013, 10:28:11 AM5/30/13
to elixir-l...@googlegroups.com
if I not mistake Regex seem better there, no ? 

f = function do              
   x -> Regex.index(%r/[^ ]*$/u, x)-1
end

f1 =  function do
   x -> Enum.reduce String.codepoints(x), {0, -1}, fn(str, { i, last_occurrence })->
        if str == " " do
             last_occurrence = i
        end
        { i + 1, last_occurrence }
        end
end

 :timer.tc(f , [x]) 
 {79,11}
 
 :timer.tc(f1 , [x]) 
 {519,{16,11}}

Alexei Sholik

unread,
May 30, 2013, 4:10:18 PM5/30/13
to elixir-l...@googlegroups.com
Yvan, this looks good. I didn't know of Regex.index function.

noodle

unread,
May 30, 2013, 6:56:19 PM5/30/13
to elixir-l...@googlegroups.com, jose....@plataformatec.com.br
José, if I understood last correctly, it only returns the last value of the string. Is that right? 

What I really want is the index of a character in a string.

noodle

unread,
May 30, 2013, 7:00:01 PM5/30/13
to elixir-l...@googlegroups.com
Agreed. It looks neat and clean. Thanks Yvan.

noodle

unread,
May 30, 2013, 7:00:51 PM5/30/13
to elixir-l...@googlegroups.com
Yvan, thank you for the proposed solutions. I was thinking of regex too. Thank your for the solution.
Reply all
Reply to author
Forward
0 new messages