שלמה גולדברג (הרב דוטנט)

מרצה ויועץ, מכללת סלע ללימודי מחשבים

האם יש טקסט עברי בתוך מחרוזת

 

כיצד ניתן לוודא האם יש עברית בתוך מחרוזת.

 
באתרי אינטרנט נהוג להשתמש בלוקליזצייה כדי להחליט האם להציג את האתר מימין לשמאל או משמאל לימין.
 
השאלה מה קורה כשמציגים בעברית ועדיין רוצים להציג קטע טקסט מסויים משמאל לימין במידה ואין בו עברית.
 
יוסי גולדברג מצא את המתודה הבאה
 

public static bool HasHebrewChar(this string value)

{

    for (int i = 0; i < value.Length; i++)

    {

        if (value[i] <= 'ת' && value[i] >= 'א')

        {

            return true;

        }

    }

    return false;

}

 
אני הייתי משנה את זה לקוד הבא.
 

public static bool HasHebrewChar(this string value)

{

    return value.ToCharArray().Any(x => (x <= 'ת' && x >= 'א'));

}

פורסם: Jul 26 2010, 09:14 PM by Shlomo | with 7 comment(s)
תגים:

תוכן התגובה

Eran Sakal כתב/ה:

למה לא להשתמש ב-regular expressions?

Regex.IsMatch(value, "[א-ת]");

# July 26, 2010 10:40 PM

Shlomo כתב/ה:

רעיון טוב לא חשבתי על זה

# July 26, 2010 11:18 PM

רון קליין כתב/ה:

שלמה, רעיון יפה, אבל שים לב שבגירסה שלך אתה יוצר מערך *חדש* של תווים, ולכן עולה צריכת הזכרון (גם אם באופן זמני).

חוץ מזה, בשני הפתרונות חשוב מאוד לשמור את קובץ המקור עצמו, שהסיומת שלו היא cs, בקידוד של יוניקוד, אחרת יכול להיות שבשרת הפרודקשן התנאי בכלל לא יתקיים. אני אומר את זה מנסיון אישי (ושברתי את הראש על זה כמה שעות...)

# July 28, 2010 12:09 PM

דניאל כץ כתב/ה:

האלגוריתם שלך דן לחומרא, אם יש תו עברי אחד במחרוזת אזי כל השורה היא עברית... זה לא תמיד נכון -  תלוי בצורך לשמו צריך לדעת את אופי המחרוזת.

כמו שהזכרת הצורך הנפוץ הוא להצגת תוכן בweb, שם צריך לדעת אם זה ltr או rtl.

בעיקרון, הבדיקה המקובלת יותר היא "first strong character", שבודקת רק את האות הראשונה אבל מתעלמת מרכאות סוגריים וכדו'.

בכל זאת, אני מציע בדיקה סטטיסטית: אם רוב האותיות ה"חזקות" הן עבריות אז יש לנו מחרוזת עברית, ואם לא - לא. במקרה של תיקו, האלגוריתם יקבע ע"פ האות ה"חזקה" הראשונה.

public static bool IsHebrewString(this string value)

{

   int balance = 0;

   int firstLetter = 0;

   for (int i = 0; i < value.Length; i++)

   {

       if (char.IsLetter(value[i]))

       {

           if ((value[i] >= (char)0x5D0) && (value[i] <= (char)0x5EA))

               balance++;

           else

               balance--;

           if (firstLetter == 0)

           {

               firstLetter = balance > 0 ? 1 : -1;

           }

       }

       if ((value.Length - (i + 1)) <= Math.Abs(balance))

           break;

   }

   if (balance == 0)

       return firstLetter > 0;

   return balance > 0;

}

האלגוריתם זה קצת יותר ארוך, כי הוא ימשיך להתבצע עד שימצא רוב וודאי לצד זה או אחר. לדעתי, זה משתלם.

# July 28, 2010 3:39 PM

Shimmy כתב/ה:

Hello Shlomo and thanks for your post.

IMHO, you should use the char comparison against its Unicode value, so the compiler doesn't even have to get the value of 'א' etc. not that this matters.

But what I did want to mention is that your function is missing vowel chars.

So if you want to include them in the check just use the following function:

using System;

using System.Linq;

namespace ConsoleApplication1

{

 static class Program

 {

   static void Main(string[] args)

   {

     char x = 'א';

     string y = "הרב הגאון דוטנט שליטא";

     Console.WriteLine("'{0}' is hebrew: {1}", x, x.IsHebrew());

     Console.WriteLine("'{0}' is hebrew: {1}", y, y.HasHebrew());

     Console.Read();

   }

   public static bool IsHebrew(this char ch)

   {

     return ch >= 0x05d0 && ch <= 0x05ea //א-ת

       || ch >= 0x0591 && ch <= 0x05c4 || ch >= 0x05f0 && ch <= 0x05f4 || ch >= 0xfb1e && ch <= 0xfb4f; //ניקוד וכו'

   }

   public static bool HasHebrew(this string value)

   {

     return value.Any(c => c.IsHebrew());

   }

 }

}

(Resource of charmap: GOTO cmd->charmap).

HTH, Shimmy

# August 8, 2010 3:35 AM

Shimmy כתב/ה:

In addition, there is no need to call 'ToCharArray' since System.String implements IEnumerable<char>, so the System.Linq.Enumerable.Any extension method applies to it anyway.

Best regards,

Shimmy

# August 8, 2010 3:38 AM

igor609 כתב/ה:

אפשר גם ככה

var re = new Regex(@"\p{IsHebrew}");

# August 8, 2010 12:10 PM
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 7 and 5 and type the answer here:


Enter the numbers above: