मुझे एक सी # विधि बनाने में सहायता की आवश्यकता है जो एक स्ट्रिंग में किसी वर्ण की Nth घटना का सूचकांक लौटाता है।
उदाहरण के लिए, 't'स्ट्रिंग में वर्ण की तीसरी घटना "dtststxtu"है 5.
(ध्यान दें कि स्ट्रिंग में 4 ts हैं।)
मुझे एक सी # विधि बनाने में सहायता की आवश्यकता है जो एक स्ट्रिंग में किसी वर्ण की Nth घटना का सूचकांक लौटाता है।
उदाहरण के लिए, 't'स्ट्रिंग में वर्ण की तीसरी घटना "dtststxtu"है 5.
(ध्यान दें कि स्ट्रिंग में 4 ts हैं।)
जवाबों:
public int GetNthIndex(string s, char t, int n)
{
int count = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == t)
{
count++;
if (count == n)
{
return i;
}
}
}
return -1;
}
यह एक बहुत क्लीनर बनाया जा सकता है, और इनपुट पर कोई जांच नहीं है।
यहाँ एक और LINQ समाधान है:
string input = "dtststx";
char searchChar = 't';
int occurrencePosition = 3; // third occurrence of the char
var result = input.Select((c, i) => new { Char = c, Index = i })
.Where(item => item.Char == searchChar)
.Skip(occurrencePosition - 1)
.FirstOrDefault();
if (result != null)
{
Console.WriteLine("Position {0} of '{1}' occurs at index: {2}",
occurrencePosition, searchChar, result.Index);
}
else
{
Console.WriteLine("Position {0} of '{1}' not found!",
occurrencePosition, searchChar);
}
बस मज़े के लिए, यहाँ एक रेगेक्स समाधान है। मैंने देखा कि कुछ लोगों ने शुरू में गिनती करने के लिए रेगेक्स का इस्तेमाल किया था, लेकिन जब सवाल बदल गया तो कोई अपडेट नहीं किया गया। यहां बताया गया है कि यह रेगेक्स के साथ कैसे किया जा सकता है - फिर से, सिर्फ मनोरंजन के लिए। पारंपरिक दृष्टिकोण सरलता के लिए सबसे अच्छा है।
string input = "dtststx";
char searchChar = 't';
int occurrencePosition = 3; // third occurrence of the char
Match match = Regex.Matches(input, Regex.Escape(searchChar.ToString()))
.Cast<Match>()
.Skip(occurrencePosition - 1)
.FirstOrDefault();
if (match != null)
Console.WriteLine("Index: " + match.Index);
else
Console.WriteLine("Match not found!");
यहाँ एक पुनरावर्ती कार्यान्वयन है - एक विस्तार विधि के रूप में, फ्रेमवर्क विधि (एस) के प्रारूप की नकल करते हुए:
public static int IndexOfNth(
this string input, string value, int startIndex, int nth)
{
if (nth < 1)
throw new NotSupportedException("Param 'nth' must be greater than 0!");
if (nth == 1)
return input.IndexOf(value, startIndex);
return input.IndexOfNth(value, input.IndexOf(value, startIndex) + 1, --nth);
}
इसके अलावा, यहां कुछ (MBUnit) यूनिट परीक्षण हैं जो आपकी मदद कर सकते हैं (यह साबित करने के लिए कि यह सही है):
[Test]
public void TestIndexOfNthWorksForNth1()
{
const string input = "foo<br />bar<br />baz<br />";
Assert.AreEqual(3, input.IndexOfNth("<br />", 0, 1));
}
[Test]
public void TestIndexOfNthWorksForNth2()
{
const string input = "foo<br />whatthedeuce<br />kthxbai<br />";
Assert.AreEqual(21, input.IndexOfNth("<br />", 0, 2));
}
[Test]
public void TestIndexOfNthWorksForNth3()
{
const string input = "foo<br />whatthedeuce<br />kthxbai<br />";
Assert.AreEqual(34, input.IndexOfNth("<br />", 0, 3));
}
अद्यतन: Nth के सूचकांक वन-लाइनर:
int NthOccurence(string s, char t, int n)
{
s.TakeWhile(c => n - (c == t)?1:0 > 0).Count();
}
अपने जोखिम पर इनका प्रयोग करें। यह होमवर्क जैसा दिखता है, इसलिए मैंने आपके खोजने के लिए कुछ कीड़े छोड़ दिए:
int CountChars(string s, char t)
{
int count = 0;
foreach (char c in s)
if (s.Equals(t)) count ++;
return count;
}
।
int CountChars(string s, char t)
{
return s.Length - s.Replace(t.ToString(), "").Length;
}
।
int CountChars(string s, char t)
{
Regex r = new Regex("[\\" + t + "]");
return r.Match(s).Count;
}
रेनोमोर ने सही टिप्पणी की कि जोएल कोएहॉर्न का वन-लाइनर काम नहीं करता है।
यहाँ एक दो-लाइनर है जो काम करता है , एक स्ट्रिंग एक्सटेंशन विधि जो किसी वर्ण की nth घटना का 0-आधारित इंडेक्स लौटाती है, या -1 यदि कोई nth घटना मौजूद नहीं है:
public static class StringExtensions
{
public static int NthIndexOf(this string s, char c, int n)
{
var takeCount = s.TakeWhile(x => (n -= (x == c ? 1 : 0)) > 0).Count();
return takeCount == s.Length ? -1 : takeCount;
}
}
जोएल का जवाब अच्छा है (और मैंने इसे उतारा)। यहाँ एक LINQ- आधारित समाधान है:
yourString.Where(c => c == 't').Count();
Whereऔर Countविधि को विधेय पारित करके इसे छोटा कर सकते हैं । ऐसा नहीं है कि इस तरह से कुछ भी गलत है।
मैं एक और उत्तर जोड़ता हूं जो अन्य विधियों की तुलना में बहुत तेज चलता है
private static int IndexOfNth(string str, char c, int nth, int startPosition = 0)
{
int index = str.IndexOf(c, startPosition);
if (index >= 0 && nth > 1)
{
return IndexOfNth(str, c, nth - 1, index + 1);
}
return index;
}
public int GetNthOccurrenceOfChar(string s, char c, int occ)
{
return String.Join(c.ToString(), s.Split(new char[] { c }, StringSplitOptions.None).Take(occ)).Length;
}
string result = "i am 'bansal.vks@gmail.com'"; // string
int in1 = result.IndexOf('\''); // get the index of first quote
int in2 = result.IndexOf('\'', in1 + 1); // get the index of second
string quoted_text = result.Substring(in1 + 1, in2 - in1); // get the string between quotes
चूंकि अंतर्निहित IndexOfफ़ंक्शन पहले से ही एक स्ट्रिंग के भीतर एक चरित्र की खोज के लिए अनुकूलित है, इसलिए एक भी तेज़ संस्करण होगा (विस्तार विधि के रूप में):
public static int NthIndexOf(this string input, char value, int n)
{
if (n <= 0) throw new ArgumentOutOfRangeException("n", n, "n is less than zero.");
int i = -1;
do
{
i = input.IndexOf(value, i + 1);
n--;
}
while (i != -1 && n > 0);
return i;
}
या स्ट्रिंग के अंत से खोज करने के लिए उपयोग करें LastIndexOf:
public static int NthLastIndexOf(this string input, char value, int n)
{
if (n <= 0) throw new ArgumentOutOfRangeException("n", n, "n is less than zero.");
int i = input.Length;
do
{
i = input.LastIndexOf(value, i - 1);
n--;
}
while (i != -1 && n > 0);
return i;
}
वर्ण की बजाय एक स्ट्रिंग के लिए खोज से पैरामीटर प्रकार बदलने के रूप में सरल है charकरने के लिए stringऔर वैकल्पिक रूप से निर्दिष्ट करने के लिए एक अधिभार जोड़ने StringComparison।
यदि आपकी रुचि है तो आप स्ट्रिंग विस्तार के तरीके भी बना सकते हैं:
public static int Search(this string yourString, string yourMarker, int yourInst = 1, bool caseSensitive = true)
{
//returns the placement of a string in another string
int num = 0;
int currentInst = 0;
//if optional argument, case sensitive is false convert string and marker to lowercase
if (!caseSensitive) { yourString = yourString.ToLower(); yourMarker = yourMarker.ToLower(); }
int myReturnValue = -1; //if nothing is found the returned integer is negative 1
while ((num + yourMarker.Length) <= yourString.Length)
{
string testString = yourString.Substring(num, yourMarker.Length);
if (testString == yourMarker)
{
currentInst++;
if (currentInst == yourInst)
{
myReturnValue = num;
break;
}
}
num++;
}
return myReturnValue;
}
public static int Search(this string yourString, char yourMarker, int yourInst = 1, bool caseSensitive = true)
{
//returns the placement of a string in another string
int num = 0;
int currentInst = 0;
var charArray = yourString.ToArray<char>();
int myReturnValue = -1;
if (!caseSensitive)
{
yourString = yourString.ToLower();
yourMarker = Char.ToLower(yourMarker);
}
while (num <= charArray.Length)
{
if (charArray[num] == yourMarker)
{
currentInst++;
if (currentInst == yourInst)
{
myReturnValue = num;
break;
}
}
num++;
}
return myReturnValue;
}
यहाँ एक और है, शायद स्ट्रिंग का सरल कार्यान्वयन IndexOfNth() साथ स्ट्रिंग ।
यहाँ stringमिलान संस्करण है:
public static int IndexOfNth(this string source, string matchString,
int charInstance,
StringComparison stringComparison = StringComparison.CurrentCulture)
{
if (string.IsNullOrEmpty(source))
return -1;
int lastPos = 0;
int count = 0;
while (count < charInstance )
{
var len = source.Length - lastPos;
lastPos = source.IndexOf(matchString, lastPos,len,stringComparison);
if (lastPos == -1)
break;
count++;
if (count == charInstance)
return lastPos;
lastPos += matchString.Length;
}
return -1;
}
और charमैच संस्करण:
public static int IndexOfNth(string source, char matchChar, int charInstance)
{
if (string.IsNullOrEmpty(source))
return -1;
if (charInstance < 1)
return -1;
int count = 0;
for (int i = 0; i < source.Length; i++)
{
if (source[i] == matchChar)
{
count++;
if (count == charInstance)
return i;
}
}
return -1;
}
मुझे लगता है कि इस तरह के निम्न स्तर के कार्यान्वयन के लिए आप ओवरहेड को कम करने के लिए LINQ, RegEx या पुनरावर्तन का उपयोग करने से दूर रहना चाहते हैं।
एक और RegEx- आधारित समाधान (अप्रयुक्त):
int NthIndexOf(string s, char t, int n) {
if(n < 0) { throw new ArgumentException(); }
if(n==1) { return s.IndexOf(t); }
if(t=="") { return 0; }
string et = RegEx.Escape(t);
string pat = "(?<="
+ Microsoft.VisualBasic.StrDup(n-1, et + @"[.\n]*") + ")"
+ et;
Match m = RegEx.Match(s, pat);
return m.Success ? m.Index : -1;
}
यह एक मैच संग्रह बनाने के लिए RegEx की आवश्यकता से थोड़ा अधिक इष्टतम होना चाहिए, केवल सभी लेकिन एक मैच को छोड़ने के लिए।
match.Successऔर पाने के NextMatchलिए एक काउंटर incrementing और जब जल्दी तोड़ने जबकि counter == index।
public static int FindOccuranceOf(this string str,char @char, int occurance)
{
var result = str.Select((x, y) => new { Letter = x, Index = y })
.Where(letter => letter.Letter == @char).ToList();
if (occurence > result.Count || occurance <= 0)
{
throw new IndexOutOfRangeException("occurance");
}
return result[occurance-1].Index ;
}
हाय सब मैं के n वें घटना को खोजने के लिए दो अधिभार तरीकों बनाया है चार और के लिए पाठ पाश, आपके आवेदन की जो वृद्धि प्रदर्शन के माध्यम से नेविगेट के बिना कम जटिलता के साथ।
public static int NthIndexOf(string text, char searchChar, int nthindex)
{
int index = -1;
try
{
var takeCount = text.TakeWhile(x => (nthindex -= (x == searchChar ? 1 : 0)) > 0).Count();
if (takeCount < text.Length) index = takeCount;
}
catch { }
return index;
}
public static int NthIndexOf(string text, string searchText, int nthindex)
{
int index = -1;
try
{
Match m = Regex.Match(text, "((" + searchText + ").*?){" + nthindex + "}");
if (m.Success) index = m.Groups[2].Captures[nthindex - 1].Index;
}
catch { }
return index;
}
जेनेरिक के लिए विस्तारित मार्क कैल्स का लिनक्यू।
using System;
using System.Collections.Generic;
using System.Linq;
namespace fNns
{
public class indexer<T> where T : IEquatable<T>
{
public T t { get; set; }
public int index { get; set; }
}
public static class fN
{
public static indexer<T> findNth<T>(IEnumerable<T> tc, T t,
int occurrencePosition) where T : IEquatable<T>
{
var result = tc.Select((ti, i) => new indexer<T> { t = ti, index = i })
.Where(item => item.t.Equals(t))
.Skip(occurrencePosition - 1)
.FirstOrDefault();
return result;
}
public static indexer<T> findNthReverse<T>(IEnumerable<T> tc, T t,
int occurrencePosition) where T : IEquatable<T>
{
var result = tc.Reverse<T>().Select((ti, i) => new indexer<T> {t = ti, index = i })
.Where(item => item.t.Equals(t))
.Skip(occurrencePosition - 1)
.FirstOrDefault();
return result;
}
}
}
कुछ परीक्षण।
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Newtonsoft.Json;
namespace FindNthNamespace.Tests
{
public class fNTests
{
[TestCase("pass", "dtststx", 't', 3, Result = "{\"t\":\"t\",\"index\":5}")]
[TestCase("pass", new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
0, 2, Result="{\"t\":0,\"index\":10}")]
public string fNMethodTest<T>(string scenario, IEnumerable<T> tc, T t, int occurrencePosition) where T : IEquatable<T>
{
Console.WriteLine(scenario);
return JsonConvert.SerializeObject(fNns.fN.findNth<T>(tc, t, occurrencePosition)).ToString();
}
[TestCase("pass", "dtststxx", 't', 3, Result = "{\"t\":\"t\",\"index\":6}")]
[TestCase("pass", new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
0, 2, Result = "{\"t\":0,\"index\":19}")]
public string fNMethodTestReverse<T>(string scenario, IEnumerable<T> tc, T t, int occurrencePosition) where T : IEquatable<T>
{
Console.WriteLine(scenario);
return JsonConvert.SerializeObject(fNns.fN.findNthReverse<T>(tc, t, occurrencePosition)).ToString();
}
}
}
public static int IndexOfAny(this string str, string[] values, int startIndex, out string selectedItem)
{
int first = -1;
selectedItem = null;
foreach (string item in values)
{
int i = str.IndexOf(item, startIndex, StringComparison.OrdinalIgnoreCase);
if (i >= 0)
{
if (first > 0)
{
if (i < first)
{
first = i;
selectedItem = item;
}
}
else
{
first = i;
selectedItem = item;
}
}
}
return first;
}
string theString = "The String";
int index = theString.NthIndexOf("THEVALUE", 3, true);