একটি স্ট্রিংয়ের নবম সংখ্যার সূচকটি পান?


100

আমি যদি অনুপস্থিত করছি একটি সুস্পষ্ট বিল্ট-ইন পদ্ধতি, দ্রুততম উপায়ে পেতে কি এন একটি স্ট্রিং মধ্যে একটি স্ট্রিং এর ম সংঘটন?

আমি বুঝতে পারি যে আমি লুপটির প্রতিটি পুনরাবৃত্তির সূচনা সূচকটি আপডেট করে সূচিপত্র পদ্ধতিটি লুপ করতে পারি । তবে এটি করা আমার পক্ষে অপব্যয় বলে মনে হচ্ছে।


আমি তার জন্য একটি নিয়মিত এক্সপ্রেশন ব্যবহার করব তারপরে আপনাকে স্ট্রিংয়ের মধ্যে স্ট্রিংয়ের মিলের সর্বোত্তম উপায় করতে হবে। এটি সম্ভব সুন্দর ডিএসএলগুলির একটিতে আমাদের যখন ব্যবহার করা উচিত তখনই উচিত। ভিবিএন-তে একটি উদাহরণ কোড সি-তে প্রায় একই রকম।
বোভিয়াম

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

উত্তর:


52

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


2
আমি মনে করি আপনার অধিকার, যদিও মনে হচ্ছে পদ্ধতিটিতে কোনও বিল্ট হওয়া উচিত, আমি নিশ্চিত যে এটি একটি সাধারণ ঘটনা।
পিটটি

4
সত্যি? জাভা এবং সি # বিকাশের প্রায় 13 বছরের মধ্যে এটি করা কখনও মনে করতে পারি না। এর অর্থ এই নয় যে আমার কখনই এটি করতে হয়নি - তবে প্রায়শই মনে রাখা যথেষ্ট নয়।
জন স্কিটি

জাভা কথা বলতে, আমরা আছে StringUtils.ordinalIndexOf()। সমস্ত লিনক এবং অন্যান্য দুর্দান্ত বৈশিষ্ট্য সহ সি # এর পক্ষে এর জন্য অন্তর্নির্মিত সমর্থন নেই। এবং হ্যাঁ আপনি যদি পার্সার এবং টোকেনাইজারের সাথে কাজ করে থাকেন তবে এর সমর্থন পাওয়া খুব জরুরি।
অ্যানি

3
@ অ্যানি: আপনি বলেছেন "আমাদের আছে" - আপনি কি অ্যাপাচি কমন্স বলতে চান? যদি তা হয় তবে আপনি নিজের জন্য তৃতীয় পক্ষের লাইব্রেরিটি জাভা জন্য যত সহজেই পারেন সহজে নেট নেট লিখতে পারেন ... তাই জাভা স্ট্যান্ডার্ড লাইব্রেরিতে এমন কিছু নেই N নেট নেই doesn't এবং অবশ্যই সি # তে আপনি এটিকে এক্সটেনশন পদ্ধতি হিসাবে যুক্ত করতে পারেন string:)
জন স্কিটি

108

আপনি সত্যিই /((s).*?){n}/স্ট্রিংয়ের N-th সংঘটন অনুসন্ধান করার জন্য নিয়মিত প্রকাশটি ব্যবহার করতে পারেন s

সি # তে এটি দেখতে দেখতে এটির মতো হতে পারে:

public static class StringExtender
{
    public static int NthIndexOf(this string target, string value, int n)
    {
        Match m = Regex.Match(target, "((" + Regex.Escape(value) + ").*?){" + n + "}");

        if (m.Success)
            return m.Groups[2].Captures[n - 1].Index;
        else
            return -1;
    }
}

দ্রষ্টব্য: আমি Regex.Escapeরেজেক্স ইঞ্জিনটির বিশেষ অর্থ রয়েছে এমন অক্ষরগুলির সন্ধানের জন্য মূল সমাধানটিতে যুক্ত করেছি।


2
আপনি পালাতে হবে value? আমার ক্ষেত্রে আমি একটি বিন্দু খুঁজছেন ছিল msdn.microsoft.com/en-us/library/...
russau

3
লক্ষ্য রেখার লাইনে ব্রেকব্যাক থাকলে এই রেজেক্স কাজ করবে না। আপনি এটা ঠিক করতে পারেন? ধন্যবাদ।
ইগনাসিও সোলার গার্সিয়া

কোনও নবম ম্যাচ না থাকলে লক করে দেখায়। আমার একটি কমা বিভাজিত মানকে 1000 মানগুলিতে সীমাবদ্ধ করা দরকার, এবং সিএসভি কম থাকলে এটি স্তব্ধ হয়ে গেল। সুতরাং @ যোগেশ - সম্ভবত কোনও দুর্দান্ত স্বীকৃত উত্তর নয়। ;) এই উত্তরের একটি বৈকল্পিক ব্যবহার করে ( এখানে স্ট্রিং সংস্করণে একটি স্ট্রিং রয়েছে ) এবং এর পরিবর্তে নবম সংখ্যাতে থামার জন্য লুপটি পরিবর্তন করে
ruffin

\-এ অনুসন্ধানের চেষ্টা করা হচ্ছে, "\\" মানটি উত্তীর্ণ হয়েছে, এবং ম্যাচ স্ট্রিংটি regex.match ফাংশনের আগে: (()। *?) {2} এর মত দেখাচ্ছে} আমি এই ত্রুটিটি পেয়েছি: "(()। *?) {2}" পার্সিং - যথেষ্ট নয়) এর। ত্রুটি ছাড়াই পিছনে স্ল্যাশগুলি সন্ধান করার জন্য সঠিক বিন্যাসটি কী?
রিচিএমএন

3
দুঃখিত তবে একটি ছোটখাটো সমালোচনা: রেজেক্স সলিউশনগুলি সাবঅপটিমাল, কারণ তখন আমাকে নবমবারের জন্য রেজেক্সগুলি পুনর্বার করতে হবে। কোডটি পড়তে বাধ্যতামূলকভাবে আরও বেশি কঠিন যখন রেজেক্সস ব্যবহার করা হয়।
মার্ক রজার্স

19

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

ফ্রেমওয়ার্ক পদ্ধতি (গুলি) এর ফর্ম্যাটটি নকল করে এখানে একটি এক্সটেনশন পদ্ধতি হিসাবে পুনরাবৃত্তিমূলক বাস্তবায়ন (উপরের ধারণার ) রয়েছে:

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);
    var idx = input.IndexOf(value, startIndex);
    if (idx == -1)
        return -1;
    return input.IndexOfNth(value, idx + 1, --nth);
}

এছাড়াও, এখানে কয়েকটি (এমবিউনিত) ইউনিট পরীক্ষা রয়েছে যা আপনাকে সহায়তা করতে পারে (এটি সঠিক প্রমাণ করতে):

using System;
using MbUnit.Framework;

namespace IndexOfNthTest
{
    [TestFixture]
    public class Tests
    {
        //has 4 instances of the 
        private const string Input = "TestTest";
        private const string Token = "Test";

        /* Test for 0th index */

        [Test]
        public void TestZero()
        {
            Assert.Throws<NotSupportedException>(
                () => Input.IndexOfNth(Token, 0, 0));
        }

        /* Test the two standard cases (1st and 2nd) */

        [Test]
        public void TestFirst()
        {
            Assert.AreEqual(0, Input.IndexOfNth("Test", 0, 1));
        }

        [Test]
        public void TestSecond()
        {
            Assert.AreEqual(4, Input.IndexOfNth("Test", 0, 2));
        }

        /* Test the 'out of bounds' case */

        [Test]
        public void TestThird()
        {
            Assert.AreEqual(-1, Input.IndexOfNth("Test", 0, 3));
        }

        /* Test the offset case (in and out of bounds) */

        [Test]
        public void TestFirstWithOneOffset()
        {
            Assert.AreEqual(4, Input.IndexOfNth("Test", 4, 1));
        }

        [Test]
        public void TestFirstWithTwoOffsets()
        {
            Assert.AreEqual(-1, Input.IndexOfNth("Test", 8, 1));
        }
    }
}

আমি ওয়েস্টনের দুর্দান্ত প্রতিক্রিয়ার ভিত্তিতে আমার ফর্ম্যাটিং এবং পরীক্ষার কেসগুলি আপডেট করেছি (ধন্যবাদ ওয়েস্টন)।
টড থমসন

14
private int IndexOfOccurence(string s, string match, int occurence)
{
    int i = 1;
    int index = 0;

    while (i <= occurence && (index = s.IndexOf(match, index + 1)) != -1)
    {
        if (i == occurence)
            return index;

        i++;
    }

    return -1;
}

অথবা এক্স # এক্সটেনশন পদ্ধতি সহ with

public static int IndexOfOccurence(this string s, string match, int occurence)
{
    int i = 1;
    int index = 0;

    while (i <= occurence && (index = s.IndexOf(match, index + 1)) != -1)
    {
        if (i == occurence)
            return index;

        i++;
    }

    return -1;
}

5
যদি আমি ভুল না হয়ে থাকি তবে এই পদ্ধতিটি ব্যর্থ হয় যদি 0 টি পজিশনের সাথে মিলের স্ট্রিং শুরু হয়, যা indexপ্রাথমিকভাবে -1 এ সেট করে সংশোধন করা যেতে পারে ।
পিটার মাজেদ

1
আপনি নাল বা ফাঁকা স্ট্রিংগুলির জন্য এবং মেলাতেও এটি দেখতে চাইতে পারেন বা এটি নকশাকৃত সিদ্ধান্ত ফেলতে পারে।

ধন্যবাদ @ পিটারমজিদ - যদি "BOB".IndexOf("B")0 প্রদান করে, তবে এই ফাংশনটি করা উচিতIndexOfOccurence("BOB", "B", 1)
পিটারএক্স

2
আপনার সম্ভবত এটির চূড়ান্ত সমাধান যেহেতু এটির উভয়ই একটি এক্সটেনশান ফাংশন রয়েছে এবং এটি রেগেক্স এবং পুনরাবৃত্তি এড়িয়ে চলে, উভয়ই কোড কম পাঠযোগ্য।
মার্ক রজার্স

প্রকৃতপক্ষে @tdyen, কোড বিশ্লেষণ ইস্যু করবে : "CA1062 প্রকাশ্য পদ্ধতি যাচাই আর্গুমেন্ট" যদি IndexOfOccurenceপরীক্ষা না করলে sহয় null। আর String.IndexOf (স্ট্রিং, Int32) নিক্ষেপ করা হবে ArgumentNullExceptionযদি matchহয় null
ডেভিডআরআর

1

String.Split()মেথডের সাথে কাজ করা এবং অনুরোধ করা ঘটনাটি অ্যারেতে রয়েছে কিনা তা পরীক্ষা করতে ভাল লাগবে, আপনার যদি সূচকের প্রয়োজন না হয় তবে সূচকের মানটি


1

কিছু বেঞ্চমার্কিংয়ের পরে, এটি সবচেয়ে সহজ এবং সবচেয়ে কার্যকর সমাধান বলে মনে হচ্ছে

public static int IndexOfNthSB(string input,
             char value, int startIndex, int nth)
        {
            if (nth < 1)
                throw new NotSupportedException("Param 'nth' must be greater than 0!");
            var nResult = 0;
            for (int i = startIndex; i < input.Length; i++)
            {
                if (input[i] == value)
                    nResult++;
                if (nResult == nth)
                    return i;
            }
            return -1;
        }

1

System.ValueTuple ftw:

var index = line.Select((x, i) => (x, i)).Where(x => x.Item1 == '"').ElementAt(5).Item2;

এটি থেকে একটি ফাংশন লিখতে হয় হোমওয়ার্ক


0

টডের উত্তর কিছুটা সহজ করা যায়।

using System;

static class MainClass {
    private static int IndexOfNth(this string target, string substring,
                                       int seqNr, int startIdx = 0)
    {
        if (seqNr < 1)
        {
            throw new IndexOutOfRangeException("Parameter 'nth' must be greater than 0.");
        }

        var idx = target.IndexOf(substring, startIdx);

        if (idx < 0 || seqNr == 1) { return idx; }

        return target.IndexOfNth(substring, --seqNr, ++idx); // skip
    }

    static void Main () {
        Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 1));
        Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 2));
        Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 3));
        Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 4));
    }
}

আউটপুট

1
3
5
-1

0

অথবা লুপ করার সময় এর সাথে এরকম কিছু

 private static int OrdinalIndexOf(string str, string substr, int n)
    {
        int pos = -1;
        do
        {
            pos = str.IndexOf(substr, pos + 1);
        } while (n-- > 0 && pos != -1);
        return pos;
    }

-4

এটি এটি করতে পারে:

Console.WriteLine(str.IndexOf((@"\")+2)+1);

2
আমি দেখছি না এটি কীভাবে কাজ করবে। এটি কী করে তার একটি সংক্ষিপ্ত বিবরণ অন্তর্ভুক্ত করতে পারেন?
বব কাউফম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.