0 d [0-9] ට වඩා අඩු කාර්යක්ෂම වේ


1251

මම කෙනෙක් භාවිතා කළ ස්ථානය පිළිතුරක් ඊයේ ප්රකාශයට පත්කෙළේය [0123456789]දී ප්රකාශන වඩා [0-9]හෝ \d. අක්ෂර කට්ටලයකට වඩා පරාසයක් හෝ ඉලක්කම් පිරිවිතරයක් භාවිතා කිරීම වඩා කාර්යක්ෂම යැයි මම කීවෙමි.

අද එය අත්හදා බැලීමට මම තීරණය කළ අතර (C # රීජෙක්ස් එන්ජිමෙහි අවම වශයෙන්) \dඅනෙක් දෙකටම වඩා බොහෝ වෙනස් බවක් නොපෙනෙන බව පෙනේ. සසම්භාවී අක්ෂර 1000 කින් යුත් අහඹු නූල් 10000 කට වඩා වැඩි මගේ පරීක්ෂණ ප්‍රතිදානය මෙන්න, සංඛ්‍යාංක 5077 ක් ඇත:

Regular expression \d           took 00:00:00.2141226 result: 5077/10000
Regular expression [0-9]        took 00:00:00.1357972 result: 5077/10000  63.42 % of first
Regular expression [0123456789] took 00:00:00.1388997 result: 5077/10000  64.87 % of first

හේතු දෙකක් නිසා එය මට පුදුමයකි:

  1. මා සිතුවේ පරාසය කට්ටලයට වඩා කාර්යක්ෂමව ක්‍රියාත්මක කරනු ඇති බවයි.
  2. මට \dවඩා නරක ඇයි කියලා තේරුම් ගන්න බැහැ [0-9]. \dකෙටියෙන් කෙටියෙන් කියවීමට වඩා වැඩි යමක් [0-9]තිබේද?

පරීක්ෂණ කේතය මෙන්න:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace SO_RegexPerformance
{
    class Program
    {
        static void Main(string[] args)
        {
            var rand = new Random(1234);
            var strings = new List<string>();
            //10K random strings
            for (var i = 0; i < 10000; i++)
            {
                //Generate random string
                var sb = new StringBuilder();
                for (var c = 0; c < 1000; c++)
                {
                    //Add a-z randomly
                    sb.Append((char)('a' + rand.Next(26)));
                }
                //In roughly 50% of them, put a digit
                if (rand.Next(2) == 0)
                {
                    //Replace one character with a digit, 0-9
                    sb[rand.Next(sb.Length)] = (char)('0' + rand.Next(10));
                }
                strings.Add(sb.ToString());
            }

            var baseTime = testPerfomance(strings, @"\d");
            Console.WriteLine();
            var testTime = testPerfomance(strings, "[0-9]");
            Console.WriteLine("  {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
            testTime = testPerfomance(strings, "[0123456789]");
            Console.WriteLine("  {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
        }

        private static TimeSpan testPerfomance(List<string> strings, string regex)
        {
            var sw = new Stopwatch();

            int successes = 0;

            var rex = new Regex(regex);

            sw.Start();
            foreach (var str in strings)
            {
                if (rex.Match(str).Success)
                {
                    successes++;
                }
            }
            sw.Stop();

            Console.Write("Regex {0,-12} took {1} result: {2}/{3}", regex, sw.Elapsed, successes, strings.Count);

            return sw.Elapsed;
        }
    }
}

178
සමහර විට \dස්ථාන සමඟ ගනුදෙනු කරයි. උදා: හෙබ්‍රෙව් ඉලක්කම් සඳහා අකුරු භාවිතා කරයි.
බාර්මාර්

6
ආශ්‍රිත: stackoverflow.com/a/6479605/674039
wim

37
\dඑකම භාෂාව විවිධ භාෂාවලින් අදහස් නොකිරීම නිසා මෙය සිත්ගන්නා ප්‍රශ්නයකි . උදාහරණයක් ලෙස ජාවා හි \d0-9 ට පමණක් ගැලපේ
රේ ටෝල්

17
Ar බාර්මාර් හෙබ්‍රෙව් සාමාන්‍යයෙන් ඉලක්කම් සඳහා අකුරු භාවිතා නොකරයි, ඒ වෙනුවට එකම ලතින් සංඛ්‍යාංක [0-9]. අකුරු ඉලක්කම් සඳහා ආදේශ කළ හැකි නමුත් මෙය දුර්ලභ භාවිතයක් වන අතර විශේෂ පද සඳහා වෙන් කර ඇත. රීජෙක්ස් විග්‍රහකය כ"ג match match ට ගැලපෙනු ඇතැයි මම අපේක්ෂා නොකරමි (כ"ג 23 සඳහා ආදේශකයක් වීමත් සමඟ). එසේම, සිනා ඉරාවානියන්ගේ පිළිතුරෙන් දැකිය හැකි පරිදි, හෙබ්‍රෙව් අක්ෂර වලංගු ගැලපීම් ලෙස නොපෙන්වයි.
යුවල් ඇඩම්

7
වෙස්ටන්ගේ කේතය ජාවා වෙත ගෙනයාම: - රීජෙක්ස් 00: 00: 00.043922 ප්‍රති result ලය: 4912/10000 - රීජෙක්ස් [0-9] ගත්තේ 00: 00: 00.073658 ප්‍රති result ලය: 4912/10000 167% පළමු - රීජෙක්ස් [ 0123456789] ලබා ගත්තේ 00: 00: 00.085799 ප්‍රති result ලය: 4912/10000 පළමු 195%
Lunchbox

Answers:


1570

\dසියලුම යුනිකෝඩ් ඉලක්කම් පරික්ෂා කරන අතර [0-9]මෙම අක්ෂර 10 ට සීමා වේ. උදාහරණයක් ලෙස, පර්සියානු ඉලක්කම්, ۱۲۳۴۵۶۷۸۹යුනිකෝඩ් ඉලක්කම් සමඟ සැසඳිය හැකි \dනමුත් නොගැලපේ [0-9].

පහත දැක්වෙන කේතය භාවිතා කර ඔබට එවැනි සියලුම අක්ෂර ලැයිස්තුවක් ජනනය කළ හැකිය:

var sb = new StringBuilder();
for(UInt16 i = 0; i < UInt16.MaxValue; i++)
{
    string str = Convert.ToChar(i).ToString();
    if (Regex.IsMatch(str, @"\d"))
        sb.Append(str);
}
Console.WriteLine(sb.ToString());

ජනනය කරන:

0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८ ९ ০১২৩৪৫৬৭৮৯੦੧੨੩੪੫੬੭੮੯૦૧૨૩૪૫૬૭૮૯ ୦୧୨୩୪୫୬୭୮୯ ௦௧௨௩௪௫௬௭௮௯౦౧౨౩౪౫౬౭౮౯೦೧೨೩೪೫೬೭೮೯൦൧൨൩൪൫൬൭൮൯๐๑๒๓๔๕๖๗๘๙໐໑໒໓໔໕໖໗໘໙༠༡༢༣༤༥༦༧༨༩၀၁၂၃၄၅၆၇၈၉႐႑႒႓႔႕႖႗႘႙០១២៣៤៥៦៧៨៩ ᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙ ᥆᥇᥈᥉᥊᥋᥌᥍᥎᥏


121
0-9 නොවන ඉලක්කම් පිළිබඳ සම්පූර්ණ ලැයිස්තුවක් මෙන්න: fileformat.info/info/unicode/category/Nd/list.htm
රොබට් මැකී

8
@ වෙස්ටන් යුනිකෝඩ් සතුව බිටු 16 බැගින් ගුවන් යානා 17 ක් ඇත. වඩාත්ම වැදගත් චරිත මූලික තලයේ ඇත, නමුත් සමහර විශේෂ අක්ෂර, වැඩි වශයෙන් චීන, අතිරේක ගුවන් යානා වල ඇත. C # හි සිටින අය සමඟ කටයුතු කිරීම ටිකක් කරදරකාරී ය.
කෝඩ්ස්ඉන්චෝස්

9
Ob රොබට්එම්සී: නිට්පික්: සම්පූර්ණ යුනිකෝඩ් අක්ෂර කට්ටලය ඇත්ත වශයෙන්ම බිට් 21 කි (බිට් 16 බැගින් වූ ගුවන් යානා 17). නමුත් ඇත්ත වශයෙන්ම 21-බිටු-දත්ත සමුදායක් ප්‍රායෝගික නැත, එබැවින් ඔබ බලයේ -2 දත්ත සමුදායක් භාවිතා කරන්නේ නම්, ඔබට බිට් 32 ක් අවශ්‍ය බව සත්‍යයකි.
sleske

3
අනුව මෙම විකිපීඩියා, නිදහස් විශ්වකෝෂය ලිපිය , යුනිකෝඩ් මූල්යායතනය 1.114.112 කේතය ලකුණු (0 0x010FFFF කිරීමට) සීමාව කවදාවත් වෙනස් කළ බව සඳහන් කර ඇත. එය unicode.org වෙත සම්බන්ධ වේ, නමුත් එහි ප්‍රකාශය මට හමු නොවීය (මට එය මග හැරී ඇත).
කීත් තොම්සන්

14
එය කිසි විටෙකත් වෙනස් නොවේ - ඔවුන්ට එය වෙනස් කිරීමට අවශ්‍ය වන තුරු.
රොබට් මැකී

272

ලේඛනයේ මෙය නොදැනීම සඳහා බයිට්බ්ලාස්ට් වෙත ණය. රීජෙක්ස් ඉදිකිරීම්කරු වෙනස් කිරීම පමණි:

var rex = new Regex(regex, RegexOptions.ECMAScript);

නව වේලාවන් ලබා දෙයි:

Regex \d           took 00:00:00.1355787 result: 5077/10000
Regex [0-9]        took 00:00:00.1360403 result: 5077/10000  100.34 % of first
Regex [0123456789] took 00:00:00.1362112 result: 5077/10000  100.47 % of first

11
මොකක්ද මේ කරන්නේ RegexOptions.ECMAScriptද?
සම්මානලාභී

7
සිට සාමාන්ය අදහස් ප්රකාශ විකල්ප : "ප්රකාශනය සඳහා සම්මතයන්-අනුකූල හැසිරීම සක්රීය කරන්න."
chrisaycock

28
X 0xFE: එතරම් නොවේ. ECMAScript( \u1234) හි යුනිකෝඩ් ගැලවීම තවමත් වලංගු වේ . එය අර්ථය (වැනි \d) වෙනස් කරන කෙටිමං අක්‍ෂර පංති සහ යුනිකෝඩ් දේපල / ස්ක්‍රිප්ට් කෙටිකතා ඉවත් කරයි (වැනි \p{N}).
ටිම් පීට්ස්කර්

9
මෙය "ඇයි" කොටසට පිළිතුරක් නොවේ. එය "රෝග ලක්ෂණ නිවැරදි කිරීම" පිළිතුරකි. තවමත් වටිනා තොරතුරු.
usr

සාමාන්‍යයෙන්, රෙග්‍රෙක්ස් යුනිකෝඩ් ගැලපීම සඳහා සහය දක්වයි. නමුත් ECMAScript එසේ නොවේ. එබැවින්, RegexOptions.ECMAScript භාවිතා කරන විට, එය ගැලපෙන්නේ ascii, එනම් 0-9 පමණි.
lzlstyle

120

සිට රීජෙක්ස් හි “\ d” යන්නෙන් ඉලක්කම් අදහස් වේද? :

[0-9]සමාන නොවේ \d. [0-9]ගැලපෙන්නේ 0123456789අක්ෂර පමණක් වන අතර, \dතරඟ [0-9]සහ වෙනත් ඉලක්කම් අක්ෂර, උදාහරණයක් ලෙස නැගෙනහිර අරාබි ඉලක්කම්٠١٢٣٤٥٦٧٨٩


49
අනුව: msdn.microsoft.com/en-us/library/20bw873z.aspx If ECMAScript-compliant behavior is specified, \d is equivalent to [0-9].
පරිශීලක 12345678

2
හහ්, මම වැරදියිද නැත්නම් සබැඳියේ මෙම වාක්‍යය ප්‍රතිවිරුද්ධ දේ කියයි. "any d ඕනෑම දශම සංඛ්‍යාංකයකට ගැලපේ. එය standard p {Nd} නිත්‍ය ප්‍රකාශන රටාවට සමාන වන අතර එයට සම්මත දශම ඉලක්කම් 0-9 මෙන්ම වෙනත් අක්ෂර කට්ටල ගණනාවක දශම සංඛ්‍යා ද ඇතුළත් වේ."
İ ස්මෙට් ඇල්කන්

3
Y බයිට්බ්ලාස්ට් ස්තූතියි, ඉදිකිරීම්කරු භාවිතා කිරීම: var rex = new Regex(regex, RegexOptions.ECMAScript);ඒවා සියල්ලම කාර්ය සාධනය අනුව වෙන් කොට හඳුනාගත නොහැකිය.
වෙස්ටන්

2
ඔහ්, කෙසේ වෙතත්, සැමට ස්තූතියි. මෙම ප්‍රශ්නය මට විශාල ඉගෙනීමක් විය.
İ ස්මෙට් ඇල්කන්

3
කරුණාකර වෙනත් ප්‍රශ්න වලින් පිළිතුරු "පිටපත් නොකරන්න". ප්‍රශ්නය අනුපිටපතක් නම්, එය සලකුණු කරන්න.
බෝල්ට්ලොක්

20

කිරීමට අමතරව ඉහළ පිළිතුර සිට සිනා Iravianian , මෙහි .NET 4.5 අනුවාදය වේ තම කේත, යුනිකෝඩ් කේතය ලකුණු පූර්ණ පරාසය භාවිතා (සිට අනුවාදය UTF16 ප්රතිදානය, පළමු පේළි තුනක් cf සහාය පමණක් බව). ඉහළ යුනිකෝඩ් ගුවන් යානා සඳහා නිසි සහායක් නොලැබීම හේතුවෙන් ඉහළ යුනිකෝඩ් ගුවන් යානා පරීක්ෂා කිරීම හා ඇතුළත් කිරීම පිළිබඳව බොහෝ අය නොදැන සිටිති. එසේ වුවද ඒවා සමහර විට වැදගත් චරිත කිහිපයක් අඩංගු වේ.

යාවත්කාලීන කරන්න

රීජෙක්ස්\d හි BMP නොවන අක්ෂර සඳහා සහය නොදක්වන හෙයින් (ස්තූතියි xanatos ), මෙහි යුනිකෝඩ් අක්ෂර දත්ත ගබඩාව භාවිතා කරන අනුවාදයකි

public static void Main()
{
    var unicodeEncoding = new UnicodeEncoding(!BitConverter.IsLittleEndian, false);
    Console.InputEncoding = unicodeEncoding;
    Console.OutputEncoding = unicodeEncoding;

    var sb = new StringBuilder();
    for (var codePoint = 0; codePoint <= 0x10ffff; codePoint++)
    {
        var isSurrogateCodePoint = codePoint <= UInt16.MaxValue 
               && (  char.IsLowSurrogate((char) codePoint) 
                  || char.IsHighSurrogate((char) codePoint)
                  );

        if (isSurrogateCodePoint)
            continue;

        var codePointString = char.ConvertFromUtf32(codePoint);

        foreach (var category in new []{
        UnicodeCategory.DecimalDigitNumber,
            UnicodeCategory.LetterNumber,
            UnicodeCategory.OtherNumber})
        {
        sb.AppendLine($"{category}");
            foreach (var ch in charInfo[category])
        {
                sb.Append(ch);
            }
            sb.AppendLine();
        }
    }
    Console.WriteLine(sb.ToString());

    Console.ReadKey();
}

පහත ප්‍රතිදානය ලබා දීම:

DecimalDigitNumber 0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८ ९ ০১২৩৪৫৬৭৮৯੦੧੨੩੪੫੬੭੮੯૦૧૨૩૪૫૬૭૮૯ ୦୧୨୩୪୫୬୭୮୯ ᭐᭑᭒᭓᭔᭕᭖᭗᭘᭙᮰᮱᮲᮳᮴᮵᮶᮷᮸᮹᱀᱁᱂᱃᱄᱅᱆᱇᱈᱉᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙꘠꘡꘢꘣꘤꘥꘦꘧꘨꘩꣐꣑꣒꣓꣔꣕꣖꣗꣘꣙꤀꤁꤂꤃꤄꤅꤆꤇꤈꤉꧐꧑꧒꧓꧔꧕꧖꧗꧘꧙꧰꧱꧲꧳꧴꧵꧶꧷꧸꧹꩐꩑꩒꩓꩔꩕꩖꩗꩘꩙꯰꯱꯲꯳꯴꯵꯶꯷꯸꯹0123456789

LetterNumber

ᛮᛯᛰⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫⅬⅭⅮⅯⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅺⅻⅼⅽⅾⅿↀↁↂↅↆↇↈ〇〡〢〣〤〥〦〧〨〩〸〹〺ꛦꛧꛨꛩꛪꛫꛬꛭꛮꛯ 𐅀𐅁𐅂𐅃𐅄𐅅𐅆𐅇𐅈𐅉𐅊𐅋𐅌𐅍𐅎𐅏𐅐𐅑𐅒𐅓𐅔𐅕𐅖𐅗𐅘𐅙𐅚𐅛𐅜𐅝𐅞𐅟𐅠𐅡𐅢𐅣𐅤𐅥𐅦𐅧𐅨𐅩𐅪𐅫𐅬𐅭𐅮𐅯𐅰𐅱𐅲𐅳𐅴 𐍁𐍊 𐏑𐏒𐏓𐏔𐏕

වෙනත් අංක ²³¹¼½¾৴৵৶৷৸৹ ୲୳୴୵୶୷ ௰௱௲ ౸౹౺౻౼౽౾𑇡𑇢𑇣𑇤𑇥𑇦𑇧𑇨𑇩𑇪𑇫𑇬𑇭𑇮𑇯𑇰𑇱𑇲𑇳𑇴 𑜺𑜻 𑣪𑣫𑣬𑣭𑣮𑣯𑣰𑣱𑣲 𖭛𖭜𖭝𖭞𖭟𖭠𖭡𝍠𝍡𝍢𝍣𝍤𝍥𝍦𝍧𝍨𝍩𝍪𝍫𝍬𝍭𝍮𝍯𝍰𝍱


කනගාටුදායක කාරණය නම් වින් 32 කොන්සෝලය තාරකා අක්ෂර පෙන්වීම නොවේ
සෙබස්තියන්

4
මට නිවැරදිව මතක නම්, කනගාටුදායක ලෙස .NET Regexහි BMP නොවන අක්ෂර සඳහා සහය නොදක්වයි. එබැවින් අවසානයේදී අක්ෂර> 0xffff රීජෙක්ස් සමඟ පරීක්ෂා කිරීම නිෂ් .ල ය.
xanatos

-1

un d සියළුම යුනිකෝඩ් පරික්ෂා කරන අතර [0-9] මෙම අක්ෂර 10 ට සීමා වේ. ඉලක්කම් 10 ක් නම්, ඔබ භාවිතා කළ යුතුය. තවත් සමහරු writing d using භාවිතා කිරීම නිර්දේශ කරමි.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.