আমি কীভাবে দুটি স্ট্রিংকে এমনভাবে প্রতিস্থাপন করতে পারি যাতে একজনের অপরটির পরিবর্তে শেষ না হয়?


162

ধরা যাক যে আমার কাছে নিম্নলিখিত কোড রয়েছে:

String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, there was a foo and a bar."
story = story.replace("foo", word1);
story = story.replace("bar", word2);

এই কোডটি চলার পরে, এর মান storyহবে"Once upon a time, there was a foo and a foo."

যদি আমি তাদের বিপরীত ক্রমে প্রতিস্থাপন করি তবে অনুরূপ সমস্যা দেখা দেয়:

String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, there was a foo and a bar."
story = story.replace("bar", word2);
story = story.replace("foo", word1);

মান storyহবে"Once upon a time, there was a bar and a bar."

আমার লক্ষ্য চালু হয় storyমধ্যে "Once upon a time, there was a bar and a foo."আমি কিভাবে যে সাধা পারে?


7
+1 অবশ্যই কিছু ফাংশন থাকা উচিত swap(String s1, String s2, String s3)যা এর s2সাথে সমস্ত ঘটনাকে অদলবদল করে s3এবং এর বিপরীতে।
রায়ান

আমরা কি অনুমান করতে পারি যে ইনপুটগুলিতে প্রতিটি অদলবদল শব্দের একমাত্র ঘটনা আছে?
আইজজা

14
কর্নার-কেস: "আব্বাবাবাবাবা" "আব" এবং "বা" অদলবদল করার সময় আমরা আউটপুট হিসাবে কী আশা করব?
হেগেন ভন ইটজেন

1
আপনার নীচে কয়েকটি ভাল সমাধান রয়েছে, তবে কেন আপনি বুঝতে পারেন যে আপনার পদ্ধতির কাজ হয়নি? প্রথমত, আপনার কাছে "সেখানে একটি ফু ও বার ছিল"। প্রথম প্রতিস্থাপন ("foo" -> "বার") পরে আপনার "একটি বার এবং একটি বার ছিল"। আপনার কাছে এখন "বার" এর 2 টি উপস্থিতি রয়েছে, তাই আপনার দ্বিতীয় প্রতিস্থাপনটি আপনি যা প্রত্যাশা করেন তা করেন না - এটি আপনার জানার কোনও উপায় নেই যা আপনি ইতিপূর্বে শেষ বারটি প্রতিস্থাপন করেন নি কেবল তাকে প্রতিস্থাপন করতে চান। নিবন্ধন করুন আমি খুঁজে পাওয়া উভয় স্ট্রিংয়ের মধ্যে প্রথমটি মেলে এবং প্রতিস্থাপনের প্রত্যাশা করব এবং তারপরে প্রতিস্থাপন বিভাগের শেষে থেকে পুনরাবৃত্তি করব।
বিকাশকারী ডেভেলপমেন্ট

1
জেরোইনের সমাধানটি আমি টেক্সট সম্পাদকদের মধ্যে প্রায়শই ব্যবহার করি, যখন আমাকে বাল্কের নাম পরিবর্তন করতে হবে। এটি সহজ, সহজেই বোঝার জন্য, কোনও বিশেষ গ্রন্থাগার প্রয়োজন নেই, এবং একটি চিন্তাধারার সাথে বোকা হতে পারে।
হট লিক্স

উত্তর:


88

অ্যাপাচি কমন্স স্ট্রিং ইউটিলসreplaceEach() থেকে পদ্ধতিটি ব্যবহার করুন :

StringUtils.replaceEach(story, new String[]{"foo", "bar"}, new String[]{"bar", "foo"})

2
অভ্যন্তরীণভাবে হ'ল প্রতিস্থাপন হ'ল কোন ধারণা?
মেরেক

3
@ মারেক খুব সম্ভবত এই ফাংশনটি অনুসন্ধান করে এবং প্রতিটি আইটেম পাওয়া যায় তা সূচী করে, তারপরে সবগুলি সূচী হয়ে যাওয়ার পরে তাদের সকলকে প্রতিস্থাপন করে।

16
আপনি এই জন্য উৎস জানতে পারেন এখানে প্রায় 4684. লাইন
Jeroen Vannevel

এটি অত্যন্ত দুঃখের বিষয় যেটি nullপাস করার পরে এটি কোনও অনিপশন ।
ডানফোল্ড

87

আপনি একটি মধ্যবর্তী মান ব্যবহার করুন (যা এখনও বাক্যে উপস্থিত নেই)।

story = story.replace("foo", "lala");
story = story.replace("bar", "foo");
story = story.replace("lala", "bar");

সমালোচনার প্রতিক্রিয়া হিসাবে: আপনি যদি zq515sqdqs5d5sq1dqs4d1q5dqqé "& d5d4sqjshsjddhhffsscc, nvùq µù µù; d & d sdq: d:;) এর মতো একটি বৃহত পর্যায়ে অস্বাভাবিক স্ট্রিং ব্যবহার করেন তবে এটি বিতর্কও বোধ করবে না এবং এটি বিতর্কও নয় যে কোনও ব্যবহারকারী এটিতে প্রবেশ করতে পারে। কেবলমাত্র সোর্স কোডটি জেনে কোনও ব্যবহারকারী হবেন কিনা তা জানার একমাত্র উপায় এবং সেই সময়ে আপনি উদ্বেগের সম্পূর্ণ অন্য স্তরের সাথে রয়েছেন।

হ্যাঁ, সম্ভবত অভিনব রেজেক্স উপায় রয়েছে। আমি এমন কিছু পাঠযোগ্য পছন্দ করি যা আমি জানি যা আমার উপরও ছড়িয়ে পড়বে না।

মন্তব্যগুলিতে @ ডেভিড কনরাড দ্বারা প্রদত্ত দুর্দান্ত পরামর্শটিও পুনর্বার :

অসম্পূর্ণ হওয়ার জন্য বেছে নেওয়া কিছু স্ট্রিং চালাকভাবে (বোকামি) ব্যবহার করবেন না। ইউনিকোড ব্যক্তিগত ব্যবহারের অঞ্চল, ইউ + E000..U + F8FF থেকে অক্ষর ব্যবহার করুন Use প্রথমে এ জাতীয় কোনও অক্ষর মুছে ফেলুন, যেহেতু বৈধভাবে ইনপুটটিতে তাদের থাকা উচিত নয় (তাদের কেবল কিছু অ্যাপ্লিকেশনের মধ্যে অ্যাপ্লিকেশন-নির্দিষ্ট অর্থ রয়েছে), তারপরে প্রতিস্থাপনের সময় এগুলি স্থানধারক হিসাবে ব্যবহার করুন।


4
@আর্শাজি আমার ধারণা, এটি আপনার "আরও ভাল" সংজ্ঞার উপর নির্ভর করে ... যদি এটি কাজ করে এবং গ্রহণযোগ্যভাবে পারফরম্যান্ট হয় তবে পরবর্তী প্রোগ্রামিংয়ের কাজে এগিয়ে যান এবং রিফ্যাক্টরিংয়ের সময় এটির উন্নতি করা আমার দৃষ্টিভঙ্গি হবে।
ম্যাট কুরব্রু

24
স্পষ্টতই "লালা" কেবল একটি উদাহরণ। উৎপাদন, আপনি ব্যবহার করা উচিত " ) àçàçlala;: D: & E & € sdq zq515sqdqs5d5sq1dqs4d1q5dqqé" । "
Jeroen Vannevel

81
অসম্পূর্ণ হওয়ার জন্য বেছে নেওয়া কিছু স্ট্রিং চালাকভাবে (বোকামি) ব্যবহার করবেন না। ইউনিকোড ব্যক্তিগত ব্যবহারের অঞ্চল, ইউ + E000..U + F8FF থেকে অক্ষর ব্যবহার করুন Use প্রথমে এ জাতীয় কোনও অক্ষর মুছে ফেলুন, যেহেতু বৈধভাবে ইনপুটটিতে তাদের থাকা উচিত নয় (তাদের কেবল কিছু অ্যাপ্লিকেশনের মধ্যে অ্যাপ্লিকেশন-নির্দিষ্ট অর্থ রয়েছে), তারপরে প্রতিস্থাপনের সময় এগুলি স্থানধারক হিসাবে ব্যবহার করুন।
ডেভিড কনরাড

22
আসলে, এটিতে ইউনিকোড এফএকিউ পড়ার পরে , আমি মনে করি ইউ + এফডিডি0..ইউ + এফডিইএফ পরিসরের ননচার্যাক্টরা আরও ভাল পছন্দ হতে পারে be
ডেভিড কনরাড

6
@ টেমিয়ার অবশ্যই, তবে কারও কি ইনপুট স্যানিটাইজ করতে হবে, তাই না? আমি আশা করব যে স্ট্রিং-রিপ্লেসমেন্ট ফাংশনটি সমস্ত স্ট্রিংয়ে কাজ করে তবে এই ফাংশনটি অনিরাপদ ইনপুটগুলির জন্য বিরতি দেয়।
নবীন

33

আপনি ব্যবহার করে Matcher#appendReplacementএবং এর মতো কিছু চেষ্টা করতে পারেন Matcher#appendTail:

String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, there was a foo and a bar.";

Pattern p = Pattern.compile("foo|bar");
Matcher m = p.matcher(story);
StringBuffer sb = new StringBuffer();
while (m.find()) {
    /* do the swap... */
    switch (m.group()) {
    case "foo":
        m.appendReplacement(sb, word1);
        break;
    case "bar":
        m.appendReplacement(sb, word2);
        break;
    default:
        /* error */
        break;
    }
}
m.appendTail(sb);

System.out.println(sb.toString());
একসময়, একটি বার এবং একটি ফু ছিল।

2
যদি foo, barএবং storyসকলের অজানা মান থাকে তবে এটি কি কাজ করে ?
স্টিফেন পি

1
@StephenP আমি মূলত হার্ড কোডেড থাকেন "foo"এবং "bar"প্রতিস্থাপন স্ট্রিং যেমন ওপি তার কোডে ছিল, কিন্তু পদ্ধতির একই ধরনের জরিমানা এমনকি যদি যারা মান পরিচিত না হয় কাজ করবে (আপনি ব্যবহার করতে হবে চাই if/ else ifএকটি পরিবর্তে switchমধ্যে while-লুপ).
আর্শাজি

6
রেজেক্স তৈরি করতে আপনাকে সতর্ক থাকতে হবে। Pattern.quoteকাজে আসবে, বা \Qএবং \E
ডেভিড কনরাড

1
@ আর্জিজি - হ্যাঁ, ওয়ার্ড 1, ওয়ার্ড 2 এবং কাহিনীটিকে পরামিতি হিসাবে গ্রহণ করার জন্য এটি নিজেকে "অদলবদল" পদ্ধতি হিসাবে প্রমাণ করেছে। +1
স্টিফেন পি

4
এমনকি ক্লিনারটি প্যাটার্নটি ব্যবহার করতে হবে (foo)|(bar)এবং তারপরে এটি পরীক্ষা m.group(1) != nullকরবে, শব্দের সাথে মিল না দেওয়ার জন্য এড়াতে।
জর্ন হোর্স্টম্যান

32

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

  • @ অ্যালানহয়ে প্রস্তাবিত StringUtils.replaceEachহিসাবে অ্যাপাচি কমন্স থেকে ব্যবহার করুন । আপনি যদি আপনার প্রকল্পে নতুন নির্ভরতা যুক্ত করতে পারেন তবে এটি একটি ভাল বিকল্প। আপনি ভাগ্যবান হতে পারেন: নির্ভরতা ইতিমধ্যে আপনার প্রকল্প অন্তর্ভুক্ত করা যেতে পারে

  • @ জিরোনের প্রস্তাবিত হিসাবে অস্থায়ী স্থানধারকটি ব্যবহার করুন এবং 2 টি পদক্ষেপে প্রতিস্থাপনটি সম্পাদন করুন:

    1. সমস্ত পাঠের নিদর্শনগুলিকে একটি অনন্য ট্যাগ দিয়ে প্রতিস্থাপন করুন যা মূল পাঠ্যে বিদ্যমান নেই
    2. আসল লক্ষ্য প্রতিস্থাপনের সাথে স্থানধারকদের প্রতিস্থাপন করুন

    এটি বেশ কয়েকটি কারণের জন্য দুর্দান্ত দৃষ্টিভঙ্গি নয়: এটি নিশ্চিত করা দরকার যে প্রথম ধাপে ব্যবহৃত ট্যাগগুলি সত্যই অনন্য; এটি সত্যিকারের প্রয়োজনের চেয়ে আরও বেশি স্ট্রিং প্রতিস্থাপনের কাজ করে

  • সমস্ত নিদর্শন থেকে একটি রেজেক্স তৈরি করুন Matcherএবং StringBuffer@ আরশাজীর পরামর্শ অনুসারে পদ্ধতিটি ব্যবহার করুন । এই ভয়ানক নয়, কিন্তু না যে মহান পারেন, যেমন Regex বিল্ডিং hackish ধরনের, এবং এটি জড়িত StringBufferযা পক্ষে সময় আগে ফ্যাশন একটি থেকে বের হয়ে StringBuilder

  • ম্যাজিক প্যাটার্নগুলিতে স্ট্রিংকে বিভক্ত করে এবং বাকী অংশগুলিতে পুনরাবৃত্তি করে @mjolka দ্বারা প্রস্তাবিত একটি পুনরাবৃত্ত সমাধানটি ব্যবহার করুন । এটি একটি সূক্ষ্ম সমাধান, কমপ্যাক্ট এবং বেশ মার্জিত। এর দুর্বলতা হ'ল সম্ভাব্য অনেকগুলি স্ট্রিং এবং কনটেনটেশন অপারেশন এবং স্ট্যাকের আকার সীমা যা সমস্ত পুনরাবৃত্ত সমাধানগুলিতে প্রয়োগ হয়

  • পাঠ্যগুলিকে শব্দের সাথে বিভক্ত করুন এবং প্রতিস্থাপনটি সুন্দরভাবে সম্পাদনের জন্য জাভা 8 টি স্ট্রিম ব্যবহার করুন @ এমএসএন্ডিফোর্ডের পরামর্শ অনুসারে, তবে অবশ্যই এটি যদি আপনি শব্দের সীমানায় বিভক্ত হয়ে ঠিক থাকেন তবে এটি সাধারণ সমাধান হিসাবে উপযুক্ত না হিসাবে কাজ করে not

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

public static String replaceEach(String text, String[] searchList, String[] replacementList) {
    // TODO: throw new IllegalArgumentException() if any param doesn't make sense
    //validateParams(text, searchList, replacementList);

    SearchTracker tracker = new SearchTracker(text, searchList, replacementList);
    if (!tracker.hasNextMatch(0)) {
        return text;
    }

    StringBuilder buf = new StringBuilder(text.length() * 2);
    int start = 0;

    do {
        SearchTracker.MatchInfo matchInfo = tracker.matchInfo;
        int textIndex = matchInfo.textIndex;
        String pattern = matchInfo.pattern;
        String replacement = matchInfo.replacement;

        buf.append(text.substring(start, textIndex));
        buf.append(replacement);

        start = textIndex + pattern.length();
    } while (tracker.hasNextMatch(start));

    return buf.append(text.substring(start)).toString();
}

private static class SearchTracker {

    private final String text;

    private final Map<String, String> patternToReplacement = new HashMap<>();
    private final Set<String> pendingPatterns = new HashSet<>();

    private MatchInfo matchInfo = null;

    private static class MatchInfo {
        private final String pattern;
        private final String replacement;
        private final int textIndex;

        private MatchInfo(String pattern, String replacement, int textIndex) {
            this.pattern = pattern;
            this.replacement = replacement;
            this.textIndex = textIndex;
        }
    }

    private SearchTracker(String text, String[] searchList, String[] replacementList) {
        this.text = text;
        for (int i = 0; i < searchList.length; ++i) {
            String pattern = searchList[i];
            patternToReplacement.put(pattern, replacementList[i]);
            pendingPatterns.add(pattern);
        }
    }

    boolean hasNextMatch(int start) {
        int textIndex = -1;
        String nextPattern = null;

        for (String pattern : new ArrayList<>(pendingPatterns)) {
            int matchIndex = text.indexOf(pattern, start);
            if (matchIndex == -1) {
                pendingPatterns.remove(pattern);
            } else {
                if (textIndex == -1 || matchIndex < textIndex) {
                    textIndex = matchIndex;
                    nextPattern = pattern;
                }
            }
        }

        if (nextPattern != null) {
            matchInfo = new MatchInfo(nextPattern, patternToReplacement.get(nextPattern), textIndex);
            return true;
        }
        return false;
    }
}

ইউনিট পরীক্ষা:

@Test
public void testSingleExact() {
    assertEquals("bar", StringUtils.replaceEach("foo", new String[]{"foo"}, new String[]{"bar"}));
}

@Test
public void testReplaceTwice() {
    assertEquals("barbar", StringUtils.replaceEach("foofoo", new String[]{"foo"}, new String[]{"bar"}));
}

@Test
public void testReplaceTwoPatterns() {
    assertEquals("barbaz", StringUtils.replaceEach("foobar",
            new String[]{"foo", "bar"},
            new String[]{"bar", "baz"}));
}

@Test
public void testReplaceNone() {
    assertEquals("foofoo", StringUtils.replaceEach("foofoo", new String[]{"x"}, new String[]{"bar"}));
}

@Test
public void testStory() {
    assertEquals("Once upon a foo, there was a bar and a baz, and another bar and a cat.",
            StringUtils.replaceEach("Once upon a baz, there was a foo and a bar, and another foo and a cat.",
                    new String[]{"foo", "bar", "baz"},
                    new String[]{"bar", "baz", "foo"})
    );
}

21

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

অন্যথায়, প্রতিস্থাপন করার জন্য পরবর্তী শব্দটি দিয়ে চালিয়ে যান।

একটি নিষ্পাপ বাস্তবায়ন এর মতো দেখতে পারে

public static String replaceAll(String input, String[] search, String[] replace) {
  return replaceAll(input, search, replace, 0);
}

private static String replaceAll(String input, String[] search, String[] replace, int i) {
  if (i == search.length) {
    return input;
  }
  int j = input.indexOf(search[i]);
  if (j == -1) {
    return replaceAll(input, search, replace, i + 1);
  }
  return replaceAll(input.substring(0, j), search, replace, i + 1) +
         replace[i] +
         replaceAll(input.substring(j + search[i].length()), search, replace, i);
}

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

String input = "Once upon a baz, there was a foo and a bar.";
String[] search = new String[] { "foo", "bar", "baz" };
String[] replace = new String[] { "bar", "baz", "foo" };
System.out.println(replaceAll(input, search, replace));

আউটপুট:

Once upon a foo, there was a bar and a baz.

একটি স্বল্প সংস্করণী সংস্করণ:

public static String replaceAll(String input, String[] search, String[] replace) {
  StringBuilder sb = new StringBuilder();
  replaceAll(sb, input, 0, input.length(), search, replace, 0);
  return sb.toString();
}

private static void replaceAll(StringBuilder sb, String input, int start, int end, String[] search, String[] replace, int i) {
  while (i < search.length && start < end) {
    int j = indexOf(input, search[i], start, end);
    if (j == -1) {
      i++;
    } else {
      replaceAll(sb, input, start, j, search, replace, i + 1);
      sb.append(replace[i]);
      start = j + search[i].length();
    }
  }
  sb.append(input, start, end);
}

দুর্ভাগ্যক্রমে, জাভা এর Stringকোন indexOf(String str, int fromIndex, int toIndex)পদ্ধতি নেই। আমি indexOfএখানে প্রয়োগ বাস্তবায়ন বাদ দিয়েছি কারণ এটি সঠিক নয় বলে আমি নিশ্চিত নই, তবে এটি এখানে পোস্ট করা বিভিন্ন সমাধানের মোটামুটি সময় সহ আদর্শের উপর পাওয়া যাবে।


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

সুন্দর, তবে 100 এমবি ইনপুট ফাইল সরবরাহ করা হলে গ্রাউন্ডে আঘাত করে its
ক্রিস্টোফ ডি ট্রয়ের

12

জাভা 8-এ ওয়ান-লাইনার:

    story = Pattern
        .compile(String.format("(?<=%1$s)|(?=%1$s)", "foo|bar"))
        .splitAsStream(story)
        .map(w -> ImmutableMap.of("bar", "foo", "foo", "bar").getOrDefault(w, w))
        .collect(Collectors.joining());
  • নজরকাড়া নিয়মিত এক্সপ্রেশন ( ?<=, ?=): http://www.regular-expressions.info/lookaround.html
  • শব্দগুলিতে যদি বিশেষ রেজেক্স অক্ষর থাকতে পারে তবে সেগুলি থেকে বাঁচতে প্যাটার্ন.কোয়েট ব্যবহার করুন।
  • আমি দৃis়তার জন্য পেয়ারা ইমট্যুটেবল ম্যাপ ব্যবহার করি তবে স্পষ্টতই অন্য কোনও মানচিত্রও কাজটি করবে।

11

এখানে একটি জাভা 8 স্ট্রিম সম্ভাবনা রয়েছে যা কারও জন্য আকর্ষণীয় হতে পারে:

String word1 = "bar";
String word2 = "foo";

String story = "Once upon a time, there was a foo and a bar.";

// Map is from untranslated word to translated word
Map<String, String> wordMap = new HashMap<>();
wordMap.put(word1, word2);
wordMap.put(word2, word1);

// Split on word boundaries so we retain whitespace.
String translated = Arrays.stream(story.split("\\b"))
    .map(w -> wordMap.getOrDefault(w,  w))
    .collect(Collectors.joining());

System.out.println(translated);

এখানে জাভা in-তে একই অ্যালগরিদমের একটি আনুমানিক চিত্র রয়েছে:

String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, there was a foo and a bar.";

// Map is from untranslated word to translated word
Map<String, String> wordMap = new HashMap<>();
wordMap.put(word1, word2);
wordMap.put(word2, word1);

// Split on word boundaries so we retain whitespace.
StringBuilder translated = new StringBuilder();
for (String w : story.split("\\b"))
{
  String tw = wordMap.get(w);
  translated.append(tw != null ? tw : w);
}

System.out.println(translated);

10
এটি একটি চমৎকার প্রস্তাব যখন যে জিনিস নিয়ে আপনি প্রতিস্থাপিত চান প্রকৃত হয় শব্দ স্থান (বা অনুরূপ) দ্বারা বিভক্ত, কিন্তু এই একটি শব্দের সাবস্ট্রিং প্রতিস্থাপন জন্য কাজ করত না।
সাইমন ফারসবার্গ

জাভা 8 স্ট্রিমের জন্য +1। খুব খারাপ এটির জন্য একটি সীমানার প্রয়োজন requires
নবীন

6

উদাহরণস্বরূপ আপনি যদি কোনও বাক্যে শব্দের প্রতিস্থাপন করতে চান যা সাদা স্থান দ্বারা পৃথক করা হয়েছে আপনার উদাহরণ হিসাবে দেখানো হয় তবে আপনি এই সাধারণ অ্যালগরিদমটি ব্যবহার করতে পারেন।

  1. সাদা জায়গায় স্প্লিট গল্প
  2. প্রতিটি উপাদান প্রতিস্থাপন করুন, যদি foo এটি বার এবং ভাইস ভার্সায় প্রতিস্থাপন করে
  3. অ্যারেটিকে আবার এক স্ট্রিংয়ে যোগ দিন

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

  1. ফু শব্দটি বিভক্ত করুন
  2. অ্যারের প্রতিটি উপাদান foo দিয়ে বার প্রতিস্থাপন করুন
  3. শেষ ব্যতীত প্রতিটি এলিমেন্টের পরে বার যুক্ত করে সেই অ্যারেটিতে যোগদান করুন

1
এটি আমিও পরামর্শ দেওয়ার কথা ভাবছিলাম। যদিও এটি একটি বিধিনিষেধ যোগ করেছে যে পাঠ্যটি ফাঁকা জায়গাগুলির শব্দ। :)
বিকাশকারী মারিয়াস ইলানাস

@ মারিউসিলেনস আমি একটি বিকল্প অ্যালগরিদম যুক্ত করেছি।
ফাস্টকোডাজভা

5

মানচিত্র ব্যবহার করে এখানে একটি জটিল উত্তর দেওয়া হচ্ছে।

private static String replaceEach(String str,Map<String, String> map) {

         Object[] keys = map.keySet().toArray();
         for(int x = 0 ; x < keys.length ; x ++ ) {
             str = str.replace((String) keys[x],"%"+x);
         }

         for(int x = 0 ; x < keys.length ; x ++) {
             str = str.replace("%"+x,map.get(keys[x]));
         }
         return str;
     }

এবং পদ্ধতি বলা হয়

Map<String, String> replaceStr = new HashMap<>();
replaceStr.put("Raffy","awesome");
replaceStr.put("awesome","Raffy");
String replaced = replaceEach("Raffy is awesome, awesome awesome is Raffy Raffy", replaceStr);

আউটপুটটি হ'ল: র্যাফি দুর্দান্ত, রাফি রাফি দুর্দান্ত ভয়ঙ্কর


1
replaced.replaceAll("Raffy", "Barney");এটির পরে দৌড়াতে এটি দীর্ঘায়িত হয়ে যাবে ... এর জন্য অপেক্ষা করুন; Dary !!!
কেয়েল

3

আপনি যদি প্রতিস্থাপনের জন্য অনুসন্ধান স্ট্রিংগুলির একাধিক ঘটনা পরিচালনা করতে সক্ষম হতে চান তবে প্রতিটি সন্ধানের শব্দটিতে স্ট্রিংকে বিভক্ত করে সহজেই তা প্রতিস্থাপন করে আপনি এটি করতে পারেন। এখানে একটি উদাহরণ:

String regex = word1 + "|" + word2;
String[] values = Pattern.compile(regex).split(story);

String result;
foreach subStr in values
{
   subStr = subStr.replace(word1, word2);
   subStr = subStr.replace(word2, word1);
   result += subStr;
}

3

আপনি নিম্নলিখিত কোড ব্লক দিয়ে আপনার লক্ষ্য অর্জন করতে পারেন:

String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, in a foo, there was a foo and a bar.";
story = String.format(story.replace(word1, "%1$s").replace(word2, "%2$s"),
    word2, word1);

এটি অর্ডার নির্বিশেষে শব্দের প্রতিস্থাপন করে। আপনি এই নীতিটি কোনও ইউটিলিটি পদ্ধতিতে প্রসারিত করতে পারেন, যেমন:

private static String replace(String source, String[] targets, String[] replacements) throws IllegalArgumentException {
    if (source == null) {
        throw new IllegalArgumentException("The parameter \"source\" cannot be null.");
    }

    if (targets == null || replacements == null) {
        throw new IllegalArgumentException("Neither parameters \"targets\" or \"replacements\" can be null.");
    }

    if (targets.length == 0 || targets.length != replacements.length) {
        throw new IllegalArgumentException("The parameters \"targets\" and \"replacements\" must have at least one item and have the same length.");
    }

    String outputMask = source;
    for (int i = 0; i < targets.length; i++) {
        outputMask = outputMask.replace(targets[i], "%" + (i + 1) + "$s");
    }

    return String.format(outputMask, (Object[])replacements);
}

যা গ্রাস করা হবে:

String story = "Once upon a time, in a foo, there was a foo and a bar.";
story = replace(story, new String[] { "bar", "foo" },
    new String[] { "foo", "bar" }));

3

এটি কাজ করে এবং সহজ:

public String replaceBoth(String text, String token1, String token2) {            
    return text.replace(token1, "\ufdd0").replace(token2, token1).replace("\ufdd0", token2);
    }

আপনি এটি এর মতো ব্যবহার করুন:

replaceBoth("Once upon a time, there was a foo and a bar.", "foo", "bar");

দ্রষ্টব্য: এই স্ট্রিংগুলিতে অক্ষর না থাকা হিসাবে গণনা করা হয় \ufdd0, যা ইউনিকোড দ্বারা অভ্যন্তরীণ ব্যবহারের জন্য স্থায়ীভাবে সংরক্ষিত একটি অক্ষর (দেখুন http://www.unicode.org/faq/private_use.html ):

আমি এটি প্রয়োজনীয় মনে করি না, তবে আপনি যদি একেবারে নিরাপদ থাকতে চান তবে আপনি এটি ব্যবহার করতে পারেন:

public String replaceBoth(String text, String token1, String token2) {
    if (text.contains("\ufdd0") || token1.contains("\ufdd0") || token2.contains("\ufdd0")) throw new IllegalArgumentException("Invalid character.");
    return text.replace(token1, "\ufdd0").replace(token2, token1).replace("\ufdd0", token2);
    }

3

একমাত্র ঘটনা অদলবদল

ইনপুটটিতে সোয়াপ্যাবল স্ট্রিংগুলির প্রতিটিের মধ্যে কেবল একটির উপস্থিতি থাকলে আপনি নিম্নলিখিতটি করতে পারেন:

যে কোনও প্রতিস্থাপনের দিকে এগিয়ে যাওয়ার আগে শব্দের উপস্থিতির সূচকগুলি পান। এর পরে আমরা কেবলমাত্র এই সূচিগুলিতে পাওয়া শব্দটি প্রতিস্থাপন করি এবং সমস্ত উপস্থিতি নয়। এই সমাধানটি StringBuilderমধ্যবর্তী Stringপছন্দগুলি ব্যবহার করে এবং উত্পাদন করে নাString.replace()

একটি বিষয় লক্ষণীয়: যদি অদলবদলের শব্দের বিভিন্ন দৈর্ঘ্য থাকে তবে প্রথম প্রতিস্থাপনের পরে দ্বিতীয় সূচকটি পরিবর্তিত হতে পারে (যদি 1 ম শব্দটি 2 য় এর আগে ঘটে) ঠিক 2 দৈর্ঘ্যের পার্থক্যের সাথে। সুতরাং দ্বিতীয় সূচকটি সারিবদ্ধ করা এই বিষয়টি নিশ্চিত করবে যে আমরা বিভিন্ন দৈর্ঘ্যের সাথে শব্দ অদলবদল করি।

public static String swap(String src, String s1, String s2) {
    StringBuilder sb = new StringBuilder(src);
    int i1 = src.indexOf(s1);
    int i2 = src.indexOf(s2);

    sb.replace(i1, i1 + s1.length(), s2); // Replace s1 with s2
    // If s1 was before s2, idx2 might have changed after the replace
    if (i1 < i2)
        i2 += s2.length() - s1.length();
    sb.replace(i2, i2 + s2.length(), s1); // Replace s2 with s1

    return sb.toString();
}

ঘটনাগুলির স্বেচ্ছাসেবী সংখ্যা মো

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

public static List<Integer> occurrences(String src, String s) {
    List<Integer> list = new ArrayList<>();
    for (int idx = 0;;)
        if ((idx = src.indexOf(s, idx)) >= 0) {
            list.add(idx);
            idx += s.length();
        } else
            return list;
}

এবং এটি ব্যবহার করে আমরা শব্দগুলি অন্য একের সাথে হ্রাস সূচক দ্বারা প্রতিস্থাপন করব (যার জন্য দুটি স্বাপযোগ্য শব্দের মধ্যে বিকল্প প্রয়োজন হতে পারে) যাতে আমাদের প্রতিস্থাপনের পরে সূচকগুলিও ঠিক করতে হবে না:

public static String swapAll(String src, String s1, String s2) {
    List<Integer> l1 = occurrences(src, s1), l2 = occurrences(src, s2);

    StringBuilder sb = new StringBuilder(src);

    // Replace occurrences by decreasing index, alternating between s1 and s2
    for (int i1 = l1.size() - 1, i2 = l2.size() - 1; i1 >= 0 || i2 >= 0;) {
        int idx1 = i1 < 0 ? -1 : l1.get(i1);
        int idx2 = i2 < 0 ? -1 : l2.get(i2);
        if (idx1 > idx2) { // Replace s1 with s2
            sb.replace(idx1, idx1 + s1.length(), s2);
            i1--;
        } else { // Replace s2 with s1
            sb.replace(idx2, idx2 + s2.length(), s1);
            i2--;
        }
    }

    return sb.toString();
}

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

@ কোডসইনচাওস এটি জাভাতে নির্বিঘ্নে কাজ করে কারণ একটি জাভা Stringএকটি অক্ষর অ্যারে এবং বাইট অ্যারে নয়। বাইটগুলিতে নয় এমন অক্ষরগুলিতে পরিচালনা Stringএবং StringBuilderপরিচালনা করার সমস্ত পদ্ধতি , যা "এনকোডিং-মুক্ত"। সুতরাং indexOfম্যাচের অনুসন্ধানের স্ট্রিংগুলির সমান (অক্ষর) দৈর্ঘ্য রয়েছে।
আইজজা

সি # এবং জাভা উভয় ক্ষেত্রেই একটি স্ট্রিং ইউটিএফ -16 কোড ইউনিটের ক্রম। সমস্যাটি হ'ল কোডপয়েন্টগুলির বিভিন্ন ক্রম রয়েছে যা ইউনিকোডকে সমতুল্য মনে করে। উদাহরণস্বরূপ äএকটি একক কোডপয়েন্ট হিসাবে বা এর aপরে সংমিশ্রণ হিসাবে এনকোড করা যেতে পারে ¨। এছাড়াও কিছু কোডপয়েন্ট রয়েছে যা শূন্য-প্রস্থ (অ) সংযুক্তকারীদের মতো উপেক্ষা করা হয়। স্ট্রিংটিতে বাইটস, অক্ষর বা যে কোনও কিছুই রয়েছে তবে এটি তুলনামূলক বিধিগুলি indexOfব্যবহার করে তা বিবেচনা করে না । এটি কোড-ইউনিট তুলনা ("অর্ডিনাল") দ্বারা কেবল কোড-ইউনিট ব্যবহার করতে পারে বা এটি ইউনিকোড সমতুল্যতা প্রয়োগ করতে পারে। আমি জানি না কোন জাভা কোনটি বেছে নিয়েছিল?
কোডসইনচাউস

উদাহরণ হিসেবে বলা যায় "ab\u00ADc".IndexOf("bc")রিটার্ন 1.net দুই অক্ষর স্ট্রিং মিলে bcতিন অক্ষর স্ট্রিং।
কোডসইনচাউস

1
@ কোডসইনচাওস আমি এখন দেখছি তার অর্থ। জাভা "ab\u00ADc".indexOf("bc")রিটার্নে -1যার অর্থ "bc"পাওয়া যায় নি "ab\u00ADc"। সুতরাং এটি এখনও দাঁড়িয়ে আছে যে জাভাতে উপরের অ্যালগরিদম কাজ করে, indexOf()ম্যাচের সন্ধানের স্ট্রিংগুলির সমান (চরিত্রের) দৈর্ঘ্য indexOf()থাকে এবং অক্ষর (কোডপয়েন্ট) মিললে কেবল মিলের প্রতিবেদন করে।
আইজজা

2

এটি ব্যবহার করে একটি পদ্ধতি লিখতে সহজ String.regionMatches:

public static String simultaneousReplace(String subject, String... pairs) {
    if (pairs.length % 2 != 0) throw new IllegalArgumentException(
        "Strings to find and replace are not paired.");
    StringBuilder sb = new StringBuilder();
    outer:
    for (int i = 0; i < subject.length(); i++) {
        for (int j = 0; j < pairs.length; j += 2) {
            String find = pairs[j];
            if (subject.regionMatches(i, find, 0, find.length())) {
                sb.append(pairs[j + 1]);
                i += find.length() - 1;
                continue outer;
            }
        }
        sb.append(subject.charAt(i));
    }
    return sb.toString();
}

পরীক্ষামূলক:

String s = "There are three cats and two dogs.";
s = simultaneousReplace(s,
    "cats", "dogs",
    "dogs", "budgies");
System.out.println(s);

আউটপুট:

তিনটি কুকুর এবং দুটি বুড়ি রয়েছে।

এটি অবিলম্বে সুস্পষ্ট নয়, তবে এর মতো একটি ক্রিয়াটি এখনও প্রতিস্থাপনগুলি নির্দিষ্ট করা ক্রমের উপর নির্ভরশীল হতে পারে। বিবেচনা:

String truth = "Java is to JavaScript";
truth += " as " + simultaneousReplace(truth,
    "JavaScript", "Hamster",
    "Java", "Ham");
System.out.println(truth);

আউটপুট:

জাভা জাভাস্ক্রিপ্ট যেমন হ্যাম হ্যামস্টারের কাছে

তবে প্রতিস্থাপনগুলি বিপরীত করুন:

truth += " as " + simultaneousReplace(truth,
    "Java", "Ham",
    "JavaScript", "Hamster");

আউটপুট:

জাভা জাভাস্ক্রিপ্ট যেমন হ্যাম হ্যামস্ক্রিপ্ট হয়

ওহো! :)

অতএব দীর্ঘতম ম্যাচটি সন্ধান করা নিশ্চিত করা কখনও কখনও দরকারী (যেমন পিএইচপি-র strtrফাংশন যেমন উদাহরণস্বরূপ)। পদ্ধতির এই সংস্করণটি এটি করবে:

public static String simultaneousReplace(String subject, String... pairs) {
    if (pairs.length % 2 != 0) throw new IllegalArgumentException(
        "Strings to find and replace are not paired.");
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < subject.length(); i++) {
        int longestMatchIndex = -1;
        int longestMatchLength = -1;
        for (int j = 0; j < pairs.length; j += 2) {
            String find = pairs[j];
            if (subject.regionMatches(i, find, 0, find.length())) {
                if (find.length() > longestMatchLength) {
                    longestMatchIndex = j;
                    longestMatchLength = find.length();
                }
            }
        }
        if (longestMatchIndex >= 0) {
            sb.append(pairs[longestMatchIndex + 1]);
            i += longestMatchLength - 1;
        } else {
            sb.append(subject.charAt(i));
        }
    }
    return sb.toString();
}

নোট করুন যে উপরের পদ্ধতিগুলি সংবেদনশীল। আপনার যদি কেস-সংবেদনশীল সংস্করণের প্রয়োজন হয় তবে উপরেরটি সংশোধন করা সহজ কারণ String.regionMatchesএকটি ignoreCaseপ্যারামিটার নিতে পারে ।


2

আপনি যদি কোনও নির্ভরতা না চান তবে আপনি কেবল এমন অ্যারে ব্যবহার করতে পারেন যা কেবলমাত্র এক-সময় পরিবর্তনের অনুমতি দেয়। এটি সবচেয়ে দক্ষ সমাধান নয়, তবে এটি কাজ করা উচিত।

public String replace(String sentence, String[]... replace){
    String[] words = sentence.split("\\s+");
    int[] lock = new int[words.length];
    StringBuilder out = new StringBuilder();

    for (int i = 0; i < words.length; i++) {
        for(String[] r : replace){
            if(words[i].contains(r[0]) && lock[i] == 0){
                words[i] = words[i].replace(r[0], r[1]);
                lock[i] = 1;
            }
        }

        out.append((i < (words.length - 1) ? words[i] + " " : words[i]));
    }

    return out.toString();
}

তারপরে, এটি পুরোপুরি কাজ করে।

String story = "Once upon a time, there was a foo and a bar.";

String[] a = {"foo", "bar"};
String[] b = {"bar", "foo"};
String[] c = {"there", "Pocahontas"};
story = replace(story, a, b, c);

System.out.println(story); // Once upon a time, Pocahontas was a bar and a foo.

2

আপনি ইনপুটটিতে একাধিক অনুসন্ধান-প্রতিস্থাপন অপারেশন করছেন are প্রতিস্থাপনের স্ট্রিংগুলিতে অনুসন্ধানের স্ট্রিং থাকাকালীন এটি অনাকাঙ্ক্ষিত ফলাফল আনবে। Foo-> বার, বার-ফু উদাহরণ বিবেচনা করুন, এখানে প্রতিটি পুনরাবৃত্তির ফলাফল রয়েছে:

  1. একসময়, এখানে একটি ফু ও বার ছিল। (ইনপুট)
  2. এক সময় ছিল, একটি বার এবং একটি বার ছিল। (Foo-> বার)
  3. এক সময়, একটি foo এবং একটি ফু ছিল। (বার-> ফু, আউটপুট)

আপনাকে ফিরে না গিয়ে এক পুনরাবৃত্তিতে প্রতিস্থাপনটি সম্পাদন করতে হবে। একটি নিষ্ঠুর-শক্তি সমাধান নীচে রয়েছে:

  1. কোনও মিল পাওয়া না পাওয়া পর্যন্ত একাধিক অনুসন্ধান স্ট্রিংয়ের জন্য বর্তমান অবস্থান থেকে শেষ পর্যন্ত ইনপুটটি অনুসন্ধান করুন
  2. মিলে যাওয়া অনুসন্ধান স্ট্রিংটি সম্পর্কিত প্রতিস্থাপন স্ট্রিংয়ের সাথে প্রতিস্থাপন করুন
  3. প্রতিস্থাপিত স্ট্রিংয়ের পরে পরবর্তী অক্ষরে বর্তমান অবস্থান সেট করুন
  4. পুনরাবৃত্তি

যেমন একটি ফাংশন String.indexOfAny(String[]) -> int[]{index, whichString}দরকারী হবে। এখানে একটি উদাহরণ (সবচেয়ে দক্ষ একটি নয়):

private static String replaceEach(String str, String[] searchWords, String[] replaceWords) {
    String ret = "";
    while (str.length() > 0) {
        int i;
        for (i = 0; i < searchWords.length; i++) {
            String search = searchWords[i];
            String replace = replaceWords[i];
            if (str.startsWith(search)) {
                ret += replace;
                str = str.substring(search.length());
                break;
            }
        }
        if (i == searchWords.length) {
            ret += str.substring(0, 1);
            str = str.substring(1);
        }
    }
    return ret;
}

কিছু পরীক্ষা:

System.out.println(replaceEach(
    "Once upon a time, there was a foo and a bar.",
    new String[]{"foo", "bar"},
    new String[]{"bar", "foo"}
));
// Once upon a time, there was a bar and a foo.

System.out.println(replaceEach(
    "a p",
    new String[]{"a", "p"},
    new String[]{"apple", "pear"}
));
// apple pear

System.out.println(replaceEach(
    "ABCDE",
    new String[]{"A", "B", "C", "D", "E"},
    new String[]{"B", "C", "E", "E", "F"}
));
// BCEEF

System.out.println(replaceEach(
    "ABCDEF",
    new String[]{"ABCDEF", "ABC", "DEF"},
    new String[]{"XXXXXX", "YYY", "ZZZ"}
));
// XXXXXX
// note the order of search strings, longer strings should be placed first 
// in order to make the replacement greedy

আইডিয়োনে ডেমো আইডিয়োন, বিকল্প কোডে
ডেমো


1

আপনি সর্বদা এটি এমন একটি শব্দ দিয়ে প্রতিস্থাপন করতে পারবেন যে আপনি নিশ্চিত যে স্ট্রিং থেকে অন্য কোথাও উপস্থিত হবে না এবং পরে দ্বিতীয়টি পরে প্রতিস্থাপন করুন:

String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, there was a foo and a bar."
story = story.replace("foo", "StringYouAreSureWillNeverOccur").replace("bar", "word2").replace("StringYouAreSureWillNeverOccur", "word1");

মনে রাখবেন যে "StringYouAreSureWillNeverOccur"ঘটলে এটি সঠিকভাবে কাজ করবে না ।


5
ইউনিকোড বেসরকারী ব্যবহারের অঞ্চল, ইউ + E000..U + F8FF থেকে একটি স্ট্রিংথ্যাটক্যানটএভারওকুর তৈরি করে অক্ষর ব্যবহার করুন। আপনি আগে থেকেই এগুলিকে ফিল্টার করতে পারবেন যেহেতু ইনপুটটিতে তাদের উপস্থিতি নেই।
ডেভিড কনরাড

অথবা ইউ + এফডিডি0..ইউ + এফডিইএফ, "ননচার্যাক্টর", যা অভ্যন্তরীণ ব্যবহারের জন্য সংরক্ষিত।
ডেভিড কনরাড

1

স্ট্রিংবিল্ডার ব্যবহার বিবেচনা করুন

তারপরে সূচিটি সংরক্ষণ করুন যেখানে প্রতিটি স্ট্রিং শুরু হওয়া উচিত। আপনি যদি প্রতিটি পজিশনে কোনও স্থান ধারক চরিত্র ব্যবহার করেন তবে এটি সরিয়ে ফেলুন এবং ব্যবহারকারীদের স্ট্রিং .োকান। তারপরে আপনি শুরু অবস্থানটিতে স্ট্রিংয়ের দৈর্ঘ্য যোগ করে শেষ অবস্থানটি মানচিত্র করতে পারেন।

String firstString = "???";
String secondString  = "???"

StringBuilder story = new StringBuilder("One upon a time, there was a " 
    + firstString
    + " and a "
    + secondString);

int  firstWord = 30;
int  secondWord = firstWord + firstString.length() + 7;

story.replace(firstWord, firstWord + firstString.length(), userStringOne);
story.replace(secondWord, secondWord + secondString.length(), userStringTwo);

firstString = userStringOne;
secondString = userStringTwo;

return story;

1

আমি কেবল যা ভাগ করতে পারি তা হ'ল আমার নিজস্ব পদ্ধতি।

আপনি একটি অস্থায়ী ব্যবহার করতে পারেন String temp = "<?>";বাString.Format();

এটি কনসোল অ্যাপ্লিকেশন এর মাধ্যমে তৈরি করা আমার উদাহরণ কোড - "আইডিয়া কেবল, সঠিক উত্তর নয়"

static void Main(string[] args)
    {
        String[] word1 = {"foo", "Once"};
        String[] word2 = {"bar", "time"};
        String story = "Once upon a time, there was a foo and a bar.";

        story = Switcher(story,word1,word2);
        Console.WriteLine(story);
        Console.Read();
    }
    // Using a temporary string.
    static string Switcher(string text, string[] target, string[] value)
    {
        string temp = "<?>";
        if (target.Length == value.Length)
        {
            for (int i = 0; i < target.Length; i++)
            {
                text = text.Replace(target[i], temp);
                text = text.Replace(value[i], target[i]);
                text = text.Replace(temp, value[i]);
            }
        }
        return text;
    }

অথবা আপনি এটি ব্যবহার করতে পারেন String.Format();

static string Switcher(string text, string[] target, string[] value)
        {
            if (target.Length == value.Length)
            {
                for (int i = 0; i < target.Length; i++)
                {
                    text = text.Replace(target[i], "{0}").Replace(value[i], "{1}");
                    text = String.Format(text, value[i], target[i]);
                }
            }
            return text;
        }

আউটপুট: time upon a Once, there was a bar and a foo.


বেশ সুন্দর। তিনি যদি "_" প্রতিস্থাপন করতে চান তবে আপনি কী করবেন?
পিয়ের-আলেকজান্ড্রে বুচার্ড

@ জেটি-AlexandreBouchard পদ্ধতি আমি মান পরিবর্তন tempথেকে "_"মধ্যে <?>। তবে প্রয়োজনে, তিনি যা করতে পারেন তা হল সেই পদ্ধতিতে আরও একটি প্যারামিটার যুক্ত করা যা সেই টেম্পটিকে পরিবর্তন করবে। - "এটাকে সরল রাখাই ভাল?"
লিওনেল সারমিয়েন্টো

আমার বক্তব্যটি হ'ল ইয়োন প্রত্যাশিত ফলাফলটির গ্যারান্টি দিতে পারে না কারণ যদি অস্থায়ী == প্রতিস্থাপন করা হয় তবে আপনার উপায় কাজ করবে না।
পিয়ের-আলেকজান্দার বোচার্ড

1

এখানে আমার সংস্করণটি যা শব্দ-ভিত্তিক:

class TextReplace
{

    public static void replaceAll (String text, String [] lookup,
                                   String [] replacement, String delimiter)
    {

        String [] words = text.split(delimiter);

        for (int i = 0; i < words.length; i++)
        {

            int j = find(lookup, words[i]);

            if (j >= 0) words[i] = replacement[j];

        }

        text = StringUtils.join(words, delimiter);

    }

    public static  int find (String [] array, String key)
    {

        for (int i = 0; i < array.length; i++)
            if (array[i].equals(key))
                return i;

        return (-1);

    }

}

1
String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, there was a foo and a bar."

ছোট্ট কৌশলযুক্ত উপায় কিন্তু আপনাকে আরও কিছু চেক করা দরকার।

স্ট্রিংকে অক্ষরের অ্যারেতে রূপান্তর করুন

   String temp[] = story.split(" ");//assume there is only spaces.

টেম্পে 2. লুপ করুন এবং এর fooসাথে barএবং এর barসাথে fooপ্রতিস্থাপনযোগ্য স্ট্রিং হওয়ার কোনও সম্ভাবনা নেই বলে প্রতিস্থাপন করুন।


1

ভাল, সংক্ষিপ্ত উত্তরটি হ'ল ...

String word1 = "bar";
String word2 = "foo";
String story = "Once upon a time, there was a foo and a bar.";
story = story.replace("foo", "@"+ word1).replace("bar", word2).replace("@" + word2, word1);
System.out.println(story);

1

এখানে পাওয়া উত্তর ব্যবহার করে আপনি যে স্ট্রিং দিয়ে প্রতিস্থাপন করতে চান তার সমস্ত উপস্থিতি খুঁজে পেতে পারেন।

সুতরাং উদাহরণস্বরূপ আপনি উপরের এসও উত্তরে কোডটি চালান। সূচকের দুটি সারণী তৈরি করুন (আসুন বলুন যে বার এবং ফু আপনার স্ট্রিংয়ের মধ্যে একবারে উপস্থিত হবে না) এবং আপনি সেই টেবিলগুলির সাথে আপনার স্ট্রিংয়ের পরিবর্তে কাজ করতে পারেন।

এখন নির্দিষ্ট সূচক অবস্থানগুলিতে প্রতিস্থাপনের জন্য আপনি ব্যবহার করতে পারেন:

public static String replaceStringAt(String s, int pos, String c) {
   return s.substring(0,pos) + c + s.substring(pos+1);
}

যেখানে posসূচক যেখানে আপনার স্ট্রিং (INDEX টেবিল আমি উপরের উদ্ধৃত থেকে) শুরু হয়। সুতরাং যাক আপনি প্রতিটি জন্য সূচি দুটি টেবিল তৈরি করেছেন। আসুন তাদের কল করুন indexBarএবং indexFoo

এখন তাদের প্রতিস্থাপনের ক্ষেত্রে আপনি কেবল দুটি লুপ চালাতে পারেন, প্রতিস্থাপনের জন্য আপনার তৈরি করতে চান।

for(int i=0;i<indexBar.Count();i++)
replaceStringAt(originalString,indexBar[i],newString);

একইভাবে অন্য লুপ indexFoo

এটি এখানে অন্যান্য উত্তরের মতো দক্ষ নাও হতে পারে তবে এটি মানচিত্র বা অন্যান্য জিনিসগুলির চেয়ে বোঝা সহজ।

এটি সর্বদা আপনার পছন্দসই ফলাফল এবং প্রতিটি স্ট্রিংয়ের একাধিক সম্ভাব্য সংঘটনগুলির জন্য দেয়। যতক্ষণ না আপনি প্রতিটি ঘটনার সূচক সঞ্চয় করেন।

এছাড়াও এই উত্তরের কোনও পুনরাবৃত্তি বা কোনও বাহ্যিক নির্ভরতা প্রয়োজন। জটিলতা যতটা যায় ততটুকুই এটি O (n স্কোয়ারড), অন্যদিকে n উভয় শব্দের সংখ্যার যোগফল।


-1

আমি এই কোডটি বিকাশ করলে সমস্যার সমাধান হবে:

public static String change(String s,String s1, String s2) {
   int length = s.length();
   int x1 = s1.length();
   int x2 = s2.length();
   int x12 = s.indexOf(s1);
   int x22 = s.indexOf(s2);
   String s3=s.substring(0, x12);
   String s4 =s.substring(x12+3, x22);
   s=s3+s2+s4+s1;
   return s;
}

প্রধান ব্যবহার change(story,word2,word1).


2
এটি কেবল তখনই কাজ করবে যদি প্রতিটি স্ট্রিংয়ের হুবহু উপস্থিতি হয়
ভিক

-1
String word1 = "bar";
String word2 = "foo";

String story = "Once upon a time, there was a foo and a bar."

story = story.replace("foo", "<foo />");
story = story.replace("bar", "<bar />");

story = story.replace("<foo />", word1);
story = story.replace("<bar />", word2);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.