Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Reversing Arabic String direction

by wael_ahmed (Initiate)
on Jul 10, 2014 at 21:20 UTC ( [id://1093127]=perlquestion: print w/replies, xml ) Need Help??

wael_ahmed has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, I have an Arabic string that contains both letters and digits. The problem is that the string appears reversed, I tried using the reverse function but it reverses both the letters and digits while I need to reverse the letters only. Please help with this issue.

Replies are listed 'Best First'.
Re: Reversing Arabic String direction
by LanX (Saint) on Jul 10, 2014 at 21:49 UTC
    I think it can be done more elegantly, but this works for me

    DB<112> $str ="a123bc45de" => "a123bc45de" DB<113> join "", reverse map { /\d/ ? $_ : scalar reverse $_ } split + /(\d+)/, $str => "ed45cb123a"

    HTH! :)

    edit
    • The split breaks the string into a list of digit and non digit substrings.
    • The map does a reverse string (scalar context) on non-digits only
    • The join concats the reversed list (list context!) again to a string

    Cheers Rolf

    (addicted to the Perl Programming Language)

      The question I had was how to handle things like "name21" or even "name_21". Both yours and my "solutions" have a problem with words like that. AppleFritter is on the right track, but I think this is the key consideration that will cause the most headaches.

      You must always remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
        nope IMHO thats the way it should be in Arabic, if numbers were reversed:

        DB<115> join "", reverse map { /\d/ ? $_ : scalar reverse $_ } split + /(\d+)/, name_21 => "21_eman"

        But I didn't check your code...

        Cheers Rolf

        (addicted to the Perl Programming Language)

Re: Reversing Arabic String direction
by Jim (Curate) on Jul 11, 2014 at 03:55 UTC

    Is this a situation that requires the application of the Unicode bidi algorithm? If it is, then perhaps the CPAN module Text::Bidi may be useful to you.

    What software are you using to determine that the Arabic characters aren't displayed in the proper direction? Maybe the problem is with this software, not the Arabic text itself.

    See Visual vs. logical ordering of text.

Re: Reversing Arabic String direction
by boftx (Deacon) on Jul 10, 2014 at 21:46 UTC

    Here is a very crude, brute-force approach. I've no doubt that one of the regex masters here can do it much more efficiently.

    use strict; use warnings; # I have no idea how unicode might affect this my $wrongway = 'This is a string with numbers 12345 that must be rever +sed without reversing the numbers.'; my @tmp; my @raw = split('',$wrongway); my @numeric; my $was_numeric = 0; for ( @raw ) { if ( /\d/ ) { push( @numeric, $_ ); $was_numeric = 1; next; } elsif ( $was_numeric ) { unshift( @tmp, @numeric ); $was_numeric = 0; @numeric = (); } unshift( @tmp, $_ ); } my $right_way =join('', @tmp); print "$wrongway\n"; print $right_way; print "\n\n";

    Again, this is very ugly but might point the way to how to approach the problem.

    You must always remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
Re: Reversing Arabic String direction
by AppleFritter (Vicar) on Jul 10, 2014 at 21:51 UTC
    Without knowing anything at all about Arabic script... off the top of my head, I'd suggest splitting your string into chunks along letter/digit boundaries, reversing not reversing each chunk as appropriate, and then putting the chunks together again in the right order.
Re: Reversing Arabic String direction
by Anonymous Monk on Jul 10, 2014 at 22:13 UTC
    Well, it's hard to tell what to do without knowing any Arabic. Try this:
    use utf8; use open qw(:encode(utf-8) :std); ... $arabic_string =~ s/(\p{L}+)/reverse $1/eg;
    You should've posted some examples. Then again, Perlmonks likes to mangle non-ASCII symbols.
      building on this, you'll need a second reverse and substitute numbers only

      DB<136> $str ="a123bc45de" => "a123bc45de" DB<137> $str2= reverse $str => "ed54cb321a" DB<138> $str2 =~ s/(\p{N}+)/reverse $1/ge => 2 DB<139> $str2 => "ed45cb123a"

      \p{N} is a guess, I'll check now¹! :)

      update

      changed order of inversion to make it clearer.

      Cheers Rolf

      (addicted to the Perl Programming Language)

      ¹) perlre only mentions \p{Digit} and \p{isDigit} ... both work for me.

        Genius! ;)
      (should be) use open qw(:encoding(utf-8) :std);
        Actually, it appears you want to reverse the whole string, rather then word-by-word. Then it wouldn't work.
Re: Reversing Arabic String direction
by BillKSmith (Monsignor) on Jul 11, 2014 at 17:29 UTC
    Combine regex with reverse.
    use strict; use warnings; my $string = '21eman 21_eman'; print scalar reverse($string =~ s/(\d+)/reverse $1/egr);
    OUTPUT:
    name_21 name21
    Bill

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1093127]
Approved by boftx
Front-paged by boftx
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2024-04-24 19:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found