স্ট্রিং থেকে বিশেষ অক্ষরগুলি সরিয়ে ফেলার সর্বাধিক দক্ষ উপায়


266

আমি একটি স্ট্রিং থেকে সমস্ত বিশেষ অক্ষর মুছে ফেলতে চাই। অনুমোদিত অক্ষরগুলি হ'ল এজেড (বড় হাতের বা ছোট হাতের অক্ষর), সংখ্যা (0-9), আন্ডারস্কোর (_), বা ডট চিহ্ন (।)।

আমার নিম্নলিখিতটি রয়েছে, এটি কাজ করে তবে আমার সন্দেহ হয় (আমি জানি!) এটি খুব দক্ষ নয়:

    public static string RemoveSpecialCharacters(string str)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.Length; i++)
        {
            if ((str[i] >= '0' && str[i] <= '9')
                || (str[i] >= 'A' && str[i] <= 'z'
                    || (str[i] == '.' || str[i] == '_')))
                {
                    sb.Append(str[i]);
                }
        }

        return sb.ToString();
    }

এটি করার সবচেয়ে কার্যকরী উপায় কী? একটি নিয়মিত প্রকাশটি কেমন হবে এবং এটি সাধারণ স্ট্রিং ম্যানিপুলেশনের সাথে কীভাবে তুলনা করে?

যে স্ট্রিংগুলি পরিষ্কার করা হবে তা বরং ছোট হবে, সাধারণত দৈর্ঘ্যে 10 থেকে 30 অক্ষরের মধ্যে থাকে।


5
আমি এটি একটি উত্তরে রাখব না কারণ এটি আর কোনও দক্ষ হবে না, তবে এখানে বেশ কয়েকটি স্ট্যাটিক চর পদ্ধতি রয়েছে charআইসলেটারঅরডিজিট () যা আপনি যদি আপনার বিবৃতিতে এটি আরও সুস্পষ্টরূপে তৈরি করতে ব্যবহার করতে পারেন।
মার্টিন হ্যারিস

5
আমি নিশ্চিত নই যে এ টু জেডের জন্য পরীক্ষা করা নিরাপদ, যাতে এটি এমন 6 টি অক্ষর নিয়ে আসে যা বর্ণানুক্রমিক নয়, যার মধ্যে কেবল একটি পছন্দসই (আন্ডারবার))
স্টিভেন সুদিত

4
আপনার কোডটি আরও পাঠযোগ্য on আপনি যদি 500 সেকেন্ডের মতো লুপে এটি না করে থাকেন তবে দক্ষতা কোনও বড় বিষয় নয়। একটি রিজেপ্স ব্যবহার করুন এবং এটি পড়া খুব সহজ হবে
বায়রন হুইটলক

4
বায়রন, আপনি সম্ভবত পাঠযোগ্যতার উপর জোর দেওয়ার প্রয়োজন সম্পর্কে সঠিক right যাইহোক, আমি রেজিএক্সপ্যাকটি পঠনযোগ্য হওয়ার বিষয়ে সংশয়ী। :-)
স্টিভেন সুদিত

2
নিয়মিত এক্সপ্রেশনগুলি পাঠযোগ্য বা না হওয়ার মতো একরকম হ'ল জার্মান পাঠযোগ্য বা না পড়ার মতো; এটি যদি আপনি এটি জানেন বা না জানেন তবে এটি নির্ভর করে (যদিও উভয় ক্ষেত্রেই আপনি এখনই ব্যাকরণীয় নিয়মগুলি নিয়ে আসবেন যা কোনও অর্থ দেয় না;)
Blixt

উত্তর:


325

আপনি কেন মনে করেন যে আপনার পদ্ধতিটি দক্ষ নয়? এটি আসলে সবচেয়ে কার্যকর উপায়গুলির মধ্যে একটি যা আপনি এটি করতে পারেন।

আপনার অবশ্যই অবশ্যই স্থানীয় ভেরিয়েবলের মধ্যে এই চরিত্রটি পড়তে হবে বা অ্যারে অ্যাক্সেসের সংখ্যা হ্রাস করতে একটি গণক ব্যবহার করা উচিত:

public static string RemoveSpecialCharacters(this string str) {
   StringBuilder sb = new StringBuilder();
   foreach (char c in str) {
      if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '.' || c == '_') {
         sb.Append(c);
      }
   }
   return sb.ToString();
}

এই দক্ষ হিসাবে একটি পদ্ধতি তৈরি করে এমন একটি জিনিস এটি ভাল স্কেল করে। কার্যকর করার সময়টি স্ট্রিংয়ের দৈর্ঘ্যের সাথে আপেক্ষিক হবে। আপনি যদি এটি বড় স্ট্রিংয়ে ব্যবহার করেন তবে কোনও দুষ্টু চমক নেই।

সম্পাদনা:
আমি একটি দ্রুত পারফরম্যান্স পরীক্ষা করেছি, প্রতিটি ক্রিয়াকলাপকে 24 টি অক্ষরের স্ট্রিং দিয়ে মিলিয়ন বার চালাচ্ছি। এগুলি ফলাফল:

আসল ফাংশন: 54.5 এমএস।
আমার প্রস্তাবিত পরিবর্তন: 47.1 এমএস।
স্ট্রিংবিল্ডার ক্ষমতা নির্ধারণ সহ খনি: 43.3 এমএস।
নিয়মিত অভিব্যক্তি: 294.4 এমএস।

সম্পাদনা 2: আমি উপরের কোডে এজেড এবং এজেডের মধ্যে পার্থক্য যুক্ত করেছি। (আমি পারফরম্যান্স পরীক্ষার পুনরায় পুনরুদ্ধার করি, এবং কোনও লক্ষণীয় পার্থক্য নেই))

3 সম্পাদনা করুন:
আমি অনুসন্ধান + চর [] সমাধান পরীক্ষা করেছি এবং এটি প্রায় 13 এমএসে চলে।

প্রদানের মূল্যটি অবশ্যই, বিশাল দেখার তালিকার সূচনা এবং স্মৃতিতে রাখা। ঠিক আছে, এটি এতটা ডেটা নয়, তবে এটি এমন তুচ্ছ কাজের জন্য অনেক বেশি ...

private static bool[] _lookup;

static Program() {
   _lookup = new bool[65536];
   for (char c = '0'; c <= '9'; c++) _lookup[c] = true;
   for (char c = 'A'; c <= 'Z'; c++) _lookup[c] = true;
   for (char c = 'a'; c <= 'z'; c++) _lookup[c] = true;
   _lookup['.'] = true;
   _lookup['_'] = true;
}

public static string RemoveSpecialCharacters(string str) {
   char[] buffer = new char[str.Length];
   int index = 0;
   foreach (char c in str) {
      if (_lookup[c]) {
         buffer[index] = c;
         index++;
      }
   }
   return new string(buffer, 0, index);
}

4
আমি রাজী. আমি কেবলমাত্র অন্য পরিবর্তনটি করব তা হল স্ট্রিংবিল্ডার কনস্ট্রাক্টরের প্রাথমিক ক্ষমতার যুক্তি যুক্ত করা, "= নতুন স্ট্রিংবিল্ডার (str.Length)"।
ডেভিড

2
আমার উত্তর, char[]পরিবর্তে বাফার ব্যবহার করে StringBuilder, আমার পরীক্ষার অনুসারে এইটির সামান্য প্রান্ত রয়েছে। (খনি যদিও কম পাঠযোগ্য, তাই ক্ষুদ্র পারফরম্যান্সের বেনিফিট সম্ভবত এটি মূল্যহীন নয়
Luke

1
@ স্টিভেন: এটি ক্ষেত্রে ভালই হতে পারে তবে মানদণ্ডগুলি তাদের পক্ষে কথা বলে! আমার পরীক্ষাগুলিতে, একটি char[]বাফার ব্যবহার করে তার চেয়ে StringBuilderকয়েক গুণ বেশি পারফরম্যান্স করা হয় ( এমনকি কিছুটা) এমনকি স্ট্রিংগুলিতে স্কেলিংয়ের পরেও যা কয়েক হাজার অক্ষরের দৈর্ঘ্য।
লুক

10
@ ডাউনভোটার: ডাউনভোট কেন? আপনি যা ভুল বলে মনে করেন তা যদি ব্যাখ্যা না করেন তবে এটি উত্তরের উন্নতি করতে পারে না।
গুফা

2
@ সিলিন্ট: না, এটি হয় না, তবে আপনার কেবল এটি একবার করা উচিত। যদি আপনি কোনও অ্যারে বরাদ্দ করেন যা আপনি প্রতিটি সময় পদ্ধতিতে কল করেন (এবং আপনি যদি পদ্ধতিটি ঘন ঘন কল করেন) তবে পদ্ধতিটি এখন পর্যন্ত সবচেয়ে ধীর হয়ে যায় এবং আবর্জনা সংগ্রহকারীকে প্রচুর কাজের কারণ করে causes
গুফা 5'15

195

ঠিক আছে, যদি না আপনার সত্যিকারের কার্যকারিতাটি আপনার কার্যকারিতা থেকে সরিয়ে নেওয়া প্রয়োজন, কেবল বজায় রাখা এবং বোঝার পক্ষে সহজ with একটি নিয়মিত প্রকাশটি দেখতে এই রকম হবে:

অতিরিক্ত পারফরম্যান্সের জন্য, আপনি এটি প্রাক-সংকলন করতে পারেন বা কেবল প্রথম কলটিতে সংকলন করতে বলতে পারেন (পরবর্তী কলগুলি দ্রুততর হবে))

public static string RemoveSpecialCharacters(string str)
{
    return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled);
}

1
আমি অনুমান করতে পারি যে এটি সম্ভবত একটি জটিল যথেষ্ট ক্যোয়ারী এটি অপের পদ্ধতির চেয়ে দ্রুততর হবে, বিশেষত প্রাক-সংকলিত হলে। তবে এর ব্যাক আপ করার কোনও প্রমাণ আমার কাছে নেই। এটি পরীক্ষা করা উচিত। এটি ধীরে ধীরে ধীর না হলে আমি এই পদ্ধতিকে নির্বিশেষে বেছে নেব, কারণ এটি পড়া এবং বজায় রাখা সহজ। +1
রোমেডোর

6
এটি খুব সাধারণ রেইজেক্স (কোনও ব্যাকট্র্যাকিং বা কোনও জটিল জিনিস নেই) তাই এটি খুব সুন্দর হওয়া উচিত।

9
@ আরমিডোর: এটি সংকলন না করে এটি প্রায় 5x ধীর, সংকলিত এটি তার পদ্ধতির চেয়ে 3x ধীর। এখনও 10x সহজ যদিও :
ডি

6
নিয়মিত প্রকাশগুলি কোনও যাদুকরী হাতুড়ি নয় এবং হ্যান্ড অপ্টিমাইজড কোডের চেয়ে দ্রুত কখনই নয়।
খ্রিস্টান ক্লাউজার

2
অপ্টিমাইজেশন সম্পর্কে নুথের বিখ্যাত উক্তিটি যারা মনে করেন তাদের জন্য, এখান থেকেই এটি শুরু করা উচিত। তারপরে, যদি আপনি খুঁজে পান যে আপনার মিলি সেকেন্ডের অতিরিক্ত হাজারতম কর্মক্ষমতা প্রয়োজন, অন্য কৌশলগুলির সাথে যান go
জন

15

আমি একটি সাধারণ সন্ধানের টেবিল তৈরির পরামর্শ দিচ্ছি, যা অক্ষরের কোনও সংমিশ্রণকে বৈধ হিসাবে সেট করতে আপনি স্ট্যাটিক কনস্ট্রাক্টরের সূচনা করতে পারেন। এটি আপনাকে দ্রুত, একক চেক করতে দেয়।

সম্পাদন করা

এছাড়াও, গতির জন্য, আপনি আপনার স্ট্রিংবিল্ডারের সক্ষমতা আপনার ইনপুট স্ট্রিংয়ের দৈর্ঘ্যে শুরু করতে চাইবেন। এটি পুনর্বিবেচনাগুলি এড়াতে পারবে। এই দুটি পদ্ধতি একসাথে আপনাকে গতি এবং নমনীয়তা উভয়ই দেবে।

অন্য সম্পাদনা

আমি মনে করি সংকলকটি এটি অপ্টিমাইজ করতে পারে তবে শৈলীর পাশাপাশি দক্ষতার হিসাবে আমি এর পরিবর্তে ভবিষ্যত প্রস্তাব দিই recommend


অ্যারেগুলির জন্য forএবং foreachঅনুরূপ কোড উত্পাদন করুন। আমি যদিও স্ট্রিং সম্পর্কে জানি না। আমি সন্দেহ করি যে স্ট্রিংয়ের অ্যারের মতো প্রকৃতি সম্পর্কে জেআইটি জানে।
খ্রিস্টান ক্লাউজার

1
আমি বাজি ধরছি আপনার [রসিকতা সরানো] চেয়ে স্ট্রিংয়ের অ্যারের মতো প্রকৃতি সম্পর্কে জেআইটি আরও জানে। আন্ডারস

আমি এটি হ্যাশসেট <চাপ> ব্যবহার করে করেছি এবং এটি তার পদ্ধতির চেয়ে প্রায় 2x ধীর। বুল [] ব্যবহার করা তার ওপিতে যে সংস্করণটি রয়েছে তার চেয়ে সবেমাত্র দ্রুত (0.0469 মিমি / ইটার বনাম 0.0559ms / ইটার) দ্রুত ... কম পাঠযোগ্য হওয়ার সমস্যা রয়েছে।
ব্যবহারকারী 7116

1
আমি বুল অ্যারে এবং কোনও ইনট অ্যারে ব্যবহারের মধ্যে কোনও পারফরম্যান্সের পার্থক্য দেখতে পেলাম না। আমি একটি বুল অ্যারে ব্যবহার করব, কারণ এটি 256 কেবি থেকে 64 কেবি থেকে দেখার টেবিলটি নামিয়ে আনে, তবে এটি এখনও এইরকম তুচ্ছ কাজের জন্য প্রচুর ডেটা ... এবং এটি কেবল প্রায় 30% দ্রুত faster
গুফা

1
@ গুফা ২) প্রদত্ত যে আমরা কেবলমাত্র বর্ণমালা এবং কয়েকটি বেসিক ল্যাটিন অক্ষর রাখছি, আমাদের কেবল কম বাইটের জন্য একটি টেবিলের প্রয়োজন, তাই আকারটি আসলেই কোনও সমস্যা নয়। আমরা যদি সাধারণ-উদ্দেশ্য হতে চাইতাম, তবে মানক ইউনিকোড কৌশলটি দ্বৈত-নির্দেশনা। অন্য কথায়, 256 সারণির রেফারেন্সের একটি সারণী, যার মধ্যে অনেকগুলি একই খালি টেবিলের দিকে নির্দেশ করে।
স্টিভেন সুদিত

12
public static string RemoveSpecialCharacters(string str)
{
    char[] buffer = new char[str.Length];
    int idx = 0;

    foreach (char c in str)
    {
        if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')
            || (c >= 'a' && c <= 'z') || (c == '.') || (c == '_'))
        {
            buffer[idx] = c;
            idx++;
        }
    }

    return new string(buffer, 0, idx);
}

1
+1, পরীক্ষিত এবং এটি স্ট্রিংবিল্ডারের চেয়ে প্রায় 40% দ্রুত। 0.0294ms / স্ট্রিং বনাম 0.0399ms / স্ট্রিং
user7116

কেবল নিশ্চিত হওয়া, আপনি কি স্ট্রিংবিল্ডারটিকে প্রাক-বরাদ্দের সাথে বা ছাড়াই বোঝাচ্ছেন?
স্টিভেন সুদিত

প্রাক-বরাদ্দ সহ, এটি চর [] বরাদ্দ এবং নতুন স্ট্রিংয়ের চেয়ে এখনও 40% ধীর।
ব্যবহারকারী 7116

2
আমি এই পছন্দ। আমি এই পদ্ধতিটি টুইট করেছিforeach (char c in input.Where(c => char.IsLetterOrDigit(c) || allowedSpecialCharacters.Any(x => x == c))) buffer[idx++] = c;
ক্রিস মেরিসিক

11

একটি নিয়মিত প্রকাশটি দেখতে পাবেন:

public string RemoveSpecialChars(string input)
{
    return Regex.Replace(input, @"[^0-9a-zA-Z\._]", string.Empty);
}

তবে যদি পারফরম্যান্স অত্যন্ত গুরুত্বপূর্ণ হয় তবে আমি আপনাকে "রেজেক্স পাথ" নির্বাচন করার আগে কিছু মানদণ্ড করার পরামর্শ দিচ্ছি ...


11

আপনি যদি অক্ষরের একটি গতিশীল তালিকা ব্যবহার করেন, লিনকুই আরও দ্রুত এবং করুণ সমাধান দিতে পারে:

public static string RemoveSpecialCharacters(string value, char[] specialCharacters)
{
    return new String(value.Except(specialCharacters).ToArray());
}

আমি এই পদ্ধতির তুলনা করেছি আগের দুটি "দ্রুত" পদ্ধতির (মুক্তির সংকলন) এর সাথে:

  • লূকএইচ দ্বারা চর অ্যারের সমাধান - 427 এমএস
  • স্ট্রিংবিল্ডার সমাধান - 429 এমএস
  • লিনকিউ (এই উত্তর) - 98 এমএস

নোট করুন যে অ্যালগরিদমটি কিছুটা সংশোধন করা হয়েছে - অক্ষরগুলি হার্ড-কোডিংয়ের পরিবর্তে অ্যারে হিসাবে দেওয়া হয়, যা কিছুটা প্রভাব ফেলতে পারে (যেমন / অন্যান্য সমাধানগুলিতে অক্ষরের অ্যারেটি পরীক্ষা করার জন্য অভ্যন্তরীণ দুর্বল লুপ থাকে)।

যদি আমি একটি লিনকিউ যেখানে ক্লজ, ব্যবহার করে একটি হার্ড-কোডেড সমাধানে স্যুইচ করি তবে ফলাফলগুলি হ'ল:

  • চর অ্যারের সমাধান - 7 এসএমএস
  • স্ট্রিংবিল্ডার দ্রবণ - 22 মিমি
  • লিনকিউ - 60 এমএস

আপনি যদি লাইনকিউ বা একটি পরিবর্তিত পদ্ধতির দিকে নজর রাখতে পারেন তবে যদি আপনি অক্ষরের তালিকাটিকে হার্ড-কোডিংয়ের পরিবর্তে আরও জেনেরিক সমাধান লেখার পরিকল্পনা করছেন। লিনকুই আপনাকে অবশ্যই সংক্ষিপ্ত, অত্যন্ত পঠনযোগ্য কোড দেয় - রেগেক্সের থেকেও বেশি।


3
এই পদ্ধতিরটি দেখতে দুর্দান্ত দেখাচ্ছে, তবে এটি কাজ করে না - ব্যতীত () একটি সেট অপারেশন, সুতরাং আপনি স্ট্রিংটিতে প্রতিটি অনন্য চরিত্রের প্রথম উপস্থিতি দিয়েই শেষ করবেন।
McKenzieG1

5

আমি বিশ্বাস করি না যে আপনার অ্যালগরিদম দক্ষ ছাড়াও কিছুই। এটি ও (এন) এবং কেবলমাত্র প্রতিটি চরিত্র একবার দেখে। যাদুকরীভাবে পরীক্ষা করার আগে মানগুলি না জানলে আপনি এর চেয়ে ভাল কিছু পাবেন না।

আমি তবে আপনার StringBuilderস্ট্রিংটির প্রাথমিক আকারের ক্ষমতাটি শুরু করতে চাই । আমি অনুমান করছি আপনার অনুধাবন করা পারফরম্যান্স সমস্যাটি মেমরি পুনরায় স্থান থেকে আসে comes

পার্শ্ব নোট: চেক করা A- zনিরাপদ নয়। আপনি সহ করছি [, \, ], ^, _, এবং `...

পার্শ্ব নোট 2: অতিরিক্ত দক্ষতার জন্য, তুলনা সংখ্যা হ্রাস করার জন্য তুলনামূলকভাবে রাখুন। (সবচেয়ে খারাপভাবে, আপনি 8 টি তুলনা কথা বলছেন, সুতরাং খুব শক্ত মনে করবেন না)) এটি আপনার প্রত্যাশিত ইনপুটটির সাথে পরিবর্তিত হয়, তবে একটি উদাহরণ হতে পারে:

if (str[i] >= '0' && str[i] <= 'z' && 
    (str[i] >= 'a' || str[i] <= '9' ||  (str[i] >= 'A' && str[i] <= 'Z') || 
    str[i] == '_') || str[i] == '.')

পার্শ্ব নোট 3: যদি আপনার কোনও কারণেই সত্যই এটি দ্রুত হওয়া প্রয়োজন, একটি স্যুইচ বিবৃতিটি দ্রুত হতে পারে। সংকলকটি আপনার জন্য একটি জাম্প টেবিল তৈরি করবে, যার ফলে কেবলমাত্র একক তুলনা হয়:

switch (str[i])
{
    case '0':
    case '1':
    .
    .
    .
    case '.':
        sb.Append(str[i]);
        break;
}

1
আমি সম্মত হই যে আপনি এইটিকে ও (এন) কে মারতে পারবেন না। যাইহোক, তুলনা প্রতি ব্যয় আছে যা হ্রাস করা যেতে পারে। একটি সারণী সন্ধানের একটি স্বল্প, স্থির ব্যয় রয়েছে, যখন আপনি আরও ব্যতিক্রম যুক্ত করার সাথে একটি সিরিজের তুলনা আরও বাড়তে চলেছে।
স্টিভেন সুদিত

সাইড নোট 3 সম্পর্কে, আপনি কি সত্যিই মনে করেন যে জাম্প টেবিলটি টেবিল দেখার চেয়ে দ্রুত হবে?
স্টিভেন সুদিত

আমি স্যুইচ সমাধানটিতে দ্রুত পারফরম্যান্স পরীক্ষা চালিয়েছি এবং এটি তুলনার মতোই সম্পাদন করে।
গুফা

@ স্টিভেন সুদিত - আমি উদ্যোগ নিয়েছিলাম তারা আসলে একই রকম। একটি পরীক্ষা চালানোর যত্ন?
এলসি

7
ও (এন) স্বরলিপি মাঝে মাঝে আমাকে বিছিন্ন করে। অ্যালগরিদম ইতিমধ্যে হে (এন) এর ভিত্তিতে লোকেরা বোকা অনুমানগুলি তৈরি করবে। যদি আমরা এই রুটিনটি পরিবর্তিত করে বিশ্বের বিপরীত দিকে একটি সার্ভারের সাথে এককালীন এসএসএল সংযোগ তৈরি করে তুলনামূলক মানটি পুনরায় অর্জন করে এমন একটি ফাংশন দিয়ে কলগুলিকে প্রতিস্থাপন করতে পারি ... তবে আপনি নিশ্চয়ই একটি দুর্দান্ত পারফরম্যান্স দেখতে পাবেন পার্থক্য এবং অ্যালগরিদম হ'ল স্টিল ও (এন)। প্রতিটি অ্যালগরিদমের জন্য ও (1) এর দাম উল্লেখযোগ্য এবং সমতুল্য নয়!
দারন


4

আপনি নিম্নলিখিত হিসাবে নিয়মিত এক্সপ্রেশন ব্যবহার করতে পারেন:

return Regex.Replace(strIn, @"[^\w\.@-]", "", RegexOptions.None, TimeSpan.FromSeconds(1.0));

3

এটা আমার ভাল লাগছে। আমি কেবলমাত্র উন্নতি করব StringBuilderস্ট্রিংয়ের দৈর্ঘ্য দিয়ে আরম্ভ করা ।

StringBuilder sb = new StringBuilder(str.Length);

3

আমি এই কোড নমুনা সাথে একমত। স্ট্রিং প্রকারের এক্সটেনশন পদ্ধতিতে আমি এটিকে আলাদা করি। যাতে আপনি এটি একটি খুব সাধারণ লাইন বা কোড ব্যবহার করতে পারেন:

string test = "abc@#$123";
test.RemoveSpecialCharacters();

আপনার পরীক্ষার জন্য গুফাকে ধন্যবাদ।

public static class MethodExtensionHelper
    {
    public static string RemoveSpecialCharacters(this string str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in str)
            {
                if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
                {
                    sb.Append(c);
                }
            }
            return sb.ToString();
        }
}

2

আমি একটি বিশেষ স্ট্রিংয়ের সাথে পাওয়া সমস্ত অক্ষরকে প্রতিস্থাপন করে "বিশেষ অক্ষরগুলি" অনুসন্ধান করার জন্য নিয়মিত এক্সপ্রেশন দিয়ে স্ট্রিং রিপ্লেসম ব্যবহার করব।


+1 অবশ্যই কম কোড এবং তাত্ক্ষণিকভাবে আরও রিডেক্স-একবার রিজেক্স উপেক্ষাযোগ্য পাঠযোগ্য।
কেনে

1
@ কেনি - আমি সম্মত মূল প্রশ্নটি এমনকি এখানেও বলা হয় যে স্ট্রিংগুলি ছোট - 10-30 টি অক্ষর। তবে স্পষ্টতই অনেক লোক মনে করে আমরা দ্বিতীয়বারের মতো সিপিইউ সময় বিক্রি করছি ...
টম বুশেল

নিয়ামক এক্সপ্রেসিন এত অলস কাজ করে o সুতরাং এটি সর্বদা ব্যবহার করা উচিত নয়।
রকঅনগম

2

কাজের জন্য আমাকে অনুরূপ কিছু করতে হয়েছিল, তবে আমার ক্ষেত্রে আমাকে সমস্ত ফিল্টার করতে হয়েছিল যা কোনও চিঠি, সংখ্যা বা সাদা জায়গা নয় (তবে আপনি সহজেই এটি আপনার প্রয়োজন অনুসারে সংশোধন করতে পারেন)। ফিল্টারিংটি জাভাস্ক্রিপ্টে ক্লায়েন্ট-সাইডে সম্পন্ন হয়েছে, তবে সুরক্ষার কারণে আমি ফিল্টারিং সার্ভার-সাইডও করছি। যেহেতু আমি বেশিরভাগ স্ট্রিং পরিষ্কার হওয়ার আশা করতে পারি, তাই সত্যই প্রয়োজন না হলে আমি স্ট্রিংটি অনুলিপি করা এড়াতে চাই। এটি আমার নীচের বাস্তবায়নে যেতে দিন, যা পরিষ্কার এবং ময়লা উভয় স্ট্রিংয়ের জন্য আরও ভাল সম্পাদন করা উচিত।

public static string EnsureOnlyLetterDigitOrWhiteSpace(string input)
{
    StringBuilder cleanedInput = null;
    for (var i = 0; i < input.Length; ++i)
    {
        var currentChar = input[i];
        var charIsValid = char.IsLetterOrDigit(currentChar) || char.IsWhiteSpace(currentChar);

        if (charIsValid)
        {
            if(cleanedInput != null)
                cleanedInput.Append(currentChar);
        }
        else
        {
            if (cleanedInput != null) continue;
            cleanedInput = new StringBuilder();
            if (i > 0)
                cleanedInput.Append(input.Substring(0, i));
        }
    }

    return cleanedInput == null ? input : cleanedInput.ToString();
}

1

এস অ্যান্ড জি এর জন্য, লিনক-আইয়েড উপায়:

var original = "(*^%foo)(@)&^@#><>?:\":';=-+_";
var valid = new char[] { 
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 
    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 
    'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', 
    '9', '0', '.', '_' };
var result = string.Join("",
    (from x in original.ToCharArray() 
     where valid.Contains(x) select x.ToString())
        .ToArray());

যাইহোক, আমি মনে করি না এটি সবচেয়ে কার্যকর উপায় হতে চলেছে।


2
এটি নয়, কারণ এটি একটি রৈখিক অনুসন্ধান।
স্টিভেন সুদিত

1
public string RemoveSpecial(string evalstr)
{
StringBuilder finalstr = new StringBuilder();
            foreach(char c in evalstr){
            int charassci = Convert.ToInt16(c);
            if (!(charassci >= 33 && charassci <= 47))// special char ???
             finalstr.append(c);
            }
return finalstr.ToString();
}

1

ব্যবহার করুন:

s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());

bool my_predicate(char c)
{
 return !(isalpha(c) || c=='_' || c==' '); // depending on you definition of special characters
}

এবং আপনি একটি পরিষ্কার স্ট্রিং পাবেন s

erase()এটি সমস্ত বিশেষ অক্ষরকে ছড়িয়ে দেবে এবং my_predicate()ফাংশনটির সাথে এটি অত্যন্ত স্বনির্ধারিত ।


1

হ্যাশসেটটি ও (1)
নিশ্চিত নয় যে এটি বিদ্যমান তুলনার তুলনায় দ্রুত

private static HashSet<char> ValidChars = new HashSet<char>() { 'a', 'b', 'c', 'A', 'B', 'C', '1', '2', '3', '_' };
public static string RemoveSpecialCharacters(string str)
{
    StringBuilder sb = new StringBuilder(str.Length / 2);
    foreach (char c in str)
    {
        if (ValidChars.Contains(c)) sb.Append(c);
    }
    return sb.ToString();
}

আমি পরীক্ষা করেছি এবং এটি গ্রহণযোগ্য উত্তরের চেয়ে দ্রুত নয়।
আমি এটি ছেড়ে দেব যেন আপনার অক্ষরের একটি কনফিগারযোগ্য সেট প্রয়োজন হয় এটি একটি ভাল সমাধান হবে।


আপনি কেন ভাবেন যে তুলনাটি ও (1) নয়?
গুফা

@ গুফা আমি নিশ্চিত নই যে এটি তা নয় এবং আমি আমার মন্তব্য সরিয়ে দিয়েছি। এবং +1। মন্তব্য করার আগে আমার আরও পরীক্ষা করা উচিত ছিল।
পাপারাজ্জো

1

আমি আশ্চর্য হয়েছি যদি একটি রেজেক্স-ভিত্তিক প্রতিস্থাপন (সম্ভবত সংকলিত) দ্রুত হয়। কেউ পরীক্ষা করে দেখতে পাবে যে কেউ এটি ~ 5 গুণ কম গতিতে পেয়েছে।

এগুলি ছাড়া, আপনার স্ট্রিংবিল্ডারটিকে একটি প্রত্যাশিত দৈর্ঘ্যের সাহায্যে সূচনা করা উচিত, যাতে মধ্যবর্তী স্ট্রিংটি বড় হওয়ার সময় চারপাশে অনুলিপি করতে না হয়।

একটি ভাল সংখ্যা হ'ল মূল স্ট্রিংয়ের দৈর্ঘ্য বা কিছুটা কম (ফাংশন ইনপুটগুলির প্রকৃতির উপর নির্ভর করে)।

অবশেষে, আপনি কোনও অক্ষর গ্রহণযোগ্য কিনা তা জানতে আপনি একটি সারণী (০.১২27 পরিসরে) ব্যবহার করতে পারেন।


একটি নিয়মিত অভিব্যক্তি ইতিমধ্যে পরীক্ষা করা হয়েছে, এবং এটি প্রায় পাঁচগুণ ধীর। ০.১২২০ সীমাতে একটি সন্ধানের টেবিলের সাথে আপনাকে এখনও সারণী ব্যবহারের আগে অক্ষর কোডটি পরীক্ষা করতে হবে, কারণ অক্ষরগুলি bit বিটের মান নয়, ১ 16 বিট মান।
গুফা 21

@ গুফা এর ... হ্যাঁ? ;)
খ্রিস্টান ক্লাউজার

1

নিম্নলিখিত কোডটিতে নিম্নলিখিত আউটপুট রয়েছে (উপসংহারটি হল আমরা অ্যারে ছোট আকারে বরাদ্দকারী কিছু মেমরি রিসোর্সগুলিও সংরক্ষণ করতে পারি):

lookup = new bool[123];

for (var c = '0'; c <= '9'; c++)
{
    lookup[c] = true; System.Diagnostics.Debug.WriteLine((int)c + ": " + (char)c);
}

for (var c = 'A'; c <= 'Z'; c++)
{
    lookup[c] = true; System.Diagnostics.Debug.WriteLine((int)c + ": " + (char)c);
}

for (var c = 'a'; c <= 'z'; c++)
{
    lookup[c] = true; System.Diagnostics.Debug.WriteLine((int)c + ": " + (char)c);
}

48: 0  
49: 1  
50: 2  
51: 3  
52: 4  
53: 5  
54: 6  
55: 7  
56: 8  
57: 9  
65: A  
66: B  
67: C  
68: D  
69: E  
70: F  
71: G  
72: H  
73: I  
74: J  
75: K  
76: L  
77: M  
78: N  
79: O  
80: P  
81: Q  
82: R  
83: S  
84: T  
85: U  
86: V  
87: W  
88: X  
89: Y  
90: Z  
97: a  
98: b  
99: c  
100: d  
101: e  
102: f  
103: g  
104: h  
105: i  
106: j  
107: k  
108: l  
109: m  
110: n  
111: o  
112: p  
113: q  
114: r  
115: s  
116: t  
117: u  
118: v  
119: w  
120: x  
121: y  
122: z  

আপনি রাশিয়ান স্থানীয় সমর্থন করতে নিম্নলিখিত কোড লাইনগুলি যুক্ত করতে পারেন (অ্যারের আকার হবে 1104):

for (var c = 'А'; c <= 'Я'; c++)
{
    lookup[c] = true; System.Diagnostics.Debug.WriteLine((int)c + ": " + (char)c);
}

for (var c = 'а'; c <= 'я'; c++)
{
    lookup[c] = true; System.Diagnostics.Debug.WriteLine((int)c + ": " + (char)c);
}

1

আমি নিশ্চিত নই যে এটি সবচেয়ে কার্যকর উপায়, তবে এটি আমার পক্ষে কাজ করে

 Public Function RemoverTildes(stIn As String) As String
    Dim stFormD As String = stIn.Normalize(NormalizationForm.FormD)
    Dim sb As New StringBuilder()

    For ich As Integer = 0 To stFormD.Length - 1
        Dim uc As UnicodeCategory = CharUnicodeInfo.GetUnicodeCategory(stFormD(ich))
        If uc <> UnicodeCategory.NonSpacingMark Then
            sb.Append(stFormD(ich))
        End If
    Next
    Return (sb.ToString().Normalize(NormalizationForm.FormC))
End Function

উত্তরটি কাজ করে তবে প্রশ্নটি সি # এর জন্য। (পিএস: আমি জানি এটি প্রায় পাঁচ বছর আগে ছিল, কিন্তু এখনও ..) আমি টেলি # ভি রূপান্তরকারীকে সি # কনভার্টারে ব্যবহার করেছি, (এবং তদ্বিপরীত) এবং কোডটি ঠিক কাজ করেছে - তবে অন্য কারও সম্পর্কে নিশ্চিত নয়। (আর একটি বিষয়, রূপান্তরকারী.টেলিক.কম )
মোমোরো

1

এখানে প্রচুর প্রস্তাবিত সমাধান রয়েছে যা অন্যদের চেয়ে কিছু বেশি দক্ষ, তবে সম্ভবত খুব পঠনযোগ্য নয়। এখানে এমন একটি যা সবচেয়ে দক্ষ নাও হতে পারে তবে বেশিরভাগ পরিস্থিতিতে অবশ্যই ব্যবহারযোগ্য এবং লিংকের পক্ষে বেশ সংক্ষিপ্ত এবং পাঠযোগ্য vera

string stringToclean = "This is a test.  Do not try this at home; you might get hurt. Don't believe it?";

var validPunctuation = new HashSet<char>(". -");

var cleanedVersion = new String(stringToclean.Where(x => (x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || validPunctuation.Contains(x)).ToArray());

var cleanedLowercaseVersion = new String(stringToclean.ToLower().Where(x => (x >= 'a' && x <= 'z') || validPunctuation.Contains(x)).ToArray());

-1
public static string RemoveSpecialCharacters(string str){
    return str.replaceAll("[^A-Za-z0-9_\\\\.]", "");
}

1
আমি ভয় পাচ্ছি replaceAllসি # স্ট্রিং ফাংশন নয় তবে জাভা বা জাভাস্ক্রিপ্ট
সিসাবা তোথ

-1
public static string RemoveAllSpecialCharacters(this string text) {
  if (string.IsNullOrEmpty(text))
    return text;

  string result = Regex.Replace(text, "[:!@#$%^&*()}{|\":?><\\[\\]\\;'/.,~]", " ");
  return result;
}

উত্তরটি ভুল। আপনি যদি রেজেক্স ব্যবহার করতে চান তবে এটি অন্তর্ভুক্ত হওয়া উচিত, একচেটিয়া নয়, কারণ আপনি এখন কিছু অক্ষর মিস করছেন। আসলে, রেগেক্সের সাথে ইতিমধ্যে উত্তর রয়েছে। এবং পূর্ণ হতে - রেজেক্স হ'ল স্বল্প হয় তারপরে সরাসরি তুলনা অক্ষর ফাংশন।
টিপাক্টোপা

-3

আপনি যদি গতি সম্পর্কে উদ্বিগ্ন হন তবে বিদ্যমান স্ট্রিংটি সম্পাদনা করতে পয়েন্টার ব্যবহার করুন। আপনি স্ট্রিংটি পিন করতে পারেন এবং এটিতে একটি পয়েন্টার পেতে পারেন, তারপরে প্রতিটি অক্ষরের উপর লুপের জন্য চালান, প্রতিস্থাপনের অক্ষর দিয়ে প্রতিটি অবৈধ অক্ষর ওভাররাইট করে। এটি অত্যন্ত দক্ষ হবে এবং কোনও নতুন স্ট্রিং মেমরি বরাদ্দকরণের প্রয়োজন হবে না। আপনাকে অনিরাপদ বিকল্পের সাথে আপনার মডিউলটিও সংকলন করতে হবে এবং পয়েন্টারগুলি ব্যবহার করার জন্য আপনার পদ্ধতি শিরোনামে "অনিরাপদ" সংশোধক যুক্ত করতে হবে।

static void Main(string[] args)
{
    string str = "string!$%with^&*invalid!!characters";
    Console.WriteLine( str ); //print original string
    FixMyString( str, ' ' );
    Console.WriteLine( str ); //print string again to verify that it has been modified
    Console.ReadLine(); //pause to leave command prompt open
}


public static unsafe void FixMyString( string str, char replacement_char )
{
    fixed (char* p_str = str)
    {
        char* c = p_str; //temp pointer, since p_str is read-only
        for (int i = 0; i < str.Length; i++, c++) //loop through each character in string, advancing the character pointer as well
            if (!IsValidChar(*c)) //check whether the current character is invalid
                (*c) = replacement_char; //overwrite character in existing string with replacement character
    }
}

public static bool IsValidChar( char c )
{
    return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '.' || c == '_');
    //return char.IsLetterOrDigit( c ) || c == '.' || c == '_'; //this may work as well
}

14
Noooooooooo! .NET এ স্ট্রিং পরিবর্তন করা হচ্ছে BAAAAAAAAAAAAD! কাঠামোর সমস্ত কিছুই নিয়মটির উপর নির্ভর করে যে স্ট্রিংগুলি অদলযোগ্য, এবং যদি আপনি এটি ভেঙে যান তবে আপনি খুব আশ্চর্যজনক পার্শ্ব প্রতিক্রিয়া পেতে পারেন ...
গুফা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.