সংগ্রহ / অ্যারে / তালিকা থেকে কমা-বিচ্ছিন্ন স্ট্রিংগুলি তৈরি করার সর্বাধিক পরিশীলিত উপায়?


98

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

select * from customer 
where customer.id in (34, 26, ..., 2);

আপনার কাছে স্ট্রিং সংগ্রহ রয়েছে এবং এই স্ট্রিংগুলির একটি কমা-বিচ্ছিন্ন তালিকা কেবল একটি স্ট্রিংয়ে তৈরি করতে চান এই প্রশ্নটি হ্রাস করে আপনি এটিকে সহজ করতে পারেন।

আমি এখনও অবধি আমার ব্যবহারটি এরকম কিছু:

String result = "";
boolean first = true;
for(String string : collectionOfStrings) {
    if(first) {
        result+=string;
        first=false;
    } else {
        result+=","+string;
    }
}

তবে আপনি এটি দেখতে খুব কুৎসিত দেখতে পারেন। প্রথম চেহারাতে সেখানে কী ঘটেছিল তা আপনি দেখতে পাচ্ছেন না, বিশেষত যখন নির্মিত স্ট্রিংগুলি (প্রতিটি এসকিউএল কোয়েরির মতো) জটিল হয়ে উঠছে।

আপনার (আরও) মার্জিত উপায় কি?


সম্ভবত উপরে বর্ণিত এসকিউএলটি দেখতে আসলে দেখতে এটির মতো হওয়া উচিত: গ্রাহক থেকে * নির্বাচন করুন যেখানে কমজারিআইড ইন (34, 26, 2);
দিনাল

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



উত্তর:


85

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


স্ট্রিংগুলি পরিবর্তনযোগ্য না হওয়ায় আপনি কোডটিতে স্ট্রিং পরিবর্তন করতে চলেছেন আপনি স্ট্রিংবিল্ডার ক্লাসটি ব্যবহার করতে পারেন।

স্ট্রিংবিল্ডার শ্রেণিটিকে একটি পরিবর্তনীয় স্ট্রিং অবজেক্ট হিসাবে দেখা যেতে পারে যা এর সামগ্রী পরিবর্তিত হলে আরও মেমরি বরাদ্দ করে।

প্রশ্নটির মূল পরামর্শটি আরও বেশি স্পষ্ট ও দক্ষতার সাথে, অনাকাঙ্ক্ষিত ট্রেলিং কমাটির যত্ন নিয়ে লেখা যেতে পারে :

    StringBuilder result = new StringBuilder();
    for(String string : collectionOfStrings) {
        result.append(string);
        result.append(",");
    }
    return result.length() > 0 ? result.substring(0, result.length() - 1): "";

7
নোট করুন যে এর জন্য আপনার সংগ্রহে কমপক্ষে একটি উপাদান থাকা প্রয়োজন।
গুস

4
শীর্ষে ভোট দেওয়া উত্তর দেখুন - code.google.com/p/guava-libraries/wiki/StringsExplained
জিমেল

খালি তালিকার জন্য প্রস্তাবিত সমাধান দেখুন See
জিমেল

4
পেয়ারার উত্তর আরও ভাল। চাকা পুনর্নবীকরণের প্রয়োজন নেই।
ডেভিডজেলসন

4
@ xtreme-biker যুক্তিসঙ্গতভাবে আধুনিক সংকলক সহ, স্ট্রিংবিল্ডার স্বয়ংক্রিয়ভাবে ব্যবহৃত হতে পারে। + = ব্যবহার করার আগে আপনার পরিবেশ পরীক্ষা করুন। দেখুন stackoverflow.com/questions/1532461/...
gimel

89

ব্যবহার করুন গুগল পেয়ারা এপিআই এর joinপদ্ধতি:

Joiner.on(",").join(collectionOfStrings);

4
আজকাল ক্লাস বলা হয় Joiner; google-collections.googlecode.com/svn/trunk/javadoc/com/google/…
জোনিক

4
এবং আজ, সংগ্রহগুলি হ্রাস করা হয়েছে। ব্যবহারের গুগল পেয়ারা পরিবর্তে।
daroo

12
এদিকে, org.apache.commons.lang.StringUtils অপরিবর্তিত রয়েছে। :-)
ওগরে গীতসংহিতা

4
পেয়ারা সরে গেছে। দেখতে github.com/google/guava/wiki/StringsExplained
gimel

77

আমি কেবল কোডটি দেখেছি যা আজ এটি করেছে did এটি অ্যাভিউঅনিউর উত্তরের একটি প্রকরণ।

collectionOfStrings = /* source string collection */;
String csList = StringUtils.join(collectionOfStrings.toArray(), ",");

StringUtils (<- commons.lang 2.x, অথবা commons.lang 3.x লিংক ) আমরা ব্যবহৃত থেকে অ্যাপাচি কমন্স


... এবং স্ট্রিংগটিলগুলি কোথা থেকে আসে?
ভিজার্ট

4
আহ, ভাল কথা। আমি সেই কোডটি দেখেছি কিছুক্ষণ হয়েছে, তবে আমি বিশ্বাস করি আমরা org.apache.commons.lang.StringUtils ব্যবহার করছিলাম।
ওগ্রে গীতসংহিতা 33


4
সুন্দর ধন্যবাদ. স্ট্রিংগিলস # জয়েনও একটি আইটেবারে কাজ করে, সুতরাং আপনার সংগ্রহকে প্রথমে অ্যারেতে রূপান্তর করার দরকার নেই।
রায়

47

আমি যে লুপটি লিখি তা হ'ল:

StringBuilder buff = new StringBuilder();
String sep = "";
for (String str : strs) {
    buff.append(sep);
    buff.append(str);
    sep = ",";
}
return buff.toString();

Sep এর অভিনয় সম্পর্কে চিন্তা করবেন না। একটি কাজ খুব দ্রুত। হটস্পট যেভাবেই কোনও লুপের প্রথম পুনরাবৃত্তিটি ছাঁটাই করে তোলে (যেমন প্রায়শই নাল এবং মনো / বিমরফিক ইনলাইনিং চেকের মতো বিজোড়াগুলি মোকাবেলা করতে হয়)।

আপনি যদি এটি প্রচুর (একাধিকবার) ব্যবহার করেন তবে এটিকে একটি ভাগ করা পদ্ধতিতে রাখুন।

এসকিউএল স্টেটমেন্টে আইডির একটি তালিকা কীভাবে সন্নিবেশ করা যায় সে সম্পর্কে স্ট্যাকওভারফ্লো সম্পর্কে আরও একটি প্রশ্ন রয়েছে।


42

জাভা 8 থেকে, আপনি ব্যবহার করতে পারেন:


4
এটা ভাল! আপনি যদি স্ট্রিং () দ্বারা আচ্ছাদিত না হয়ে একটি বিশেষ স্ট্রিং রূপান্তর প্রয়োজন এমন বস্তুগুলিতে হেরফের করছেন তবে অবজেক্ট :: টু স্ট্রিংকে java.util.function.Function <আপনার টাইপ, স্ট্রিং> দিয়ে প্রতিস্থাপন করুন যা আপনার ক্লাসকে একটি স্ট্রিংয়ে ম্যাপ করে।
তোড়বেন

4
এছাড়াও, আপনি এটির মতো এটি ব্যবহার করতে পারেন: cats.stream().map(cat -> cat.getName()).collect(Collectors.joining(","));আপনার সংগ্রহ থেকে একক ভেরিয়েবলের জন্য।
numsu

আমি তার অভিনয় সম্পর্কে অবাক stream। ইনট [] বা দীর্ঘ [] বা অন্যান্য অ্যারের জন্য যেখানে মানটি সহজেই কাস্ট করা যায় String, আমি একটি স্ট্রিমিং স্ট্রিম সমাধান খুঁজছি। আসলে আমি খুঁজছি।
আদম

11

আমি পুনরাবৃত্তি আইডিয়োম মার্জিত দেখতে পেয়েছি, কারণ এটি আরও উপাদান জন্য পরীক্ষা আছে (বক্রতা জন্য নাল / খালি পরীক্ষা):

public static String convert(List<String> list) {
    String res = "";
    for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
        res += iterator.next() + (iterator.hasNext() ? "," : "");
    }
    return res;
}

... এবং সম্ভবত কম দক্ষ যে 'হ্যাশনেস্ট ()' কলটি কতটা জটিল তার উপর নির্ভর করে গ্রহণযোগ্য সমাধান। তদ্ব্যতীত, আপনার সম্ভবত স্ট্রিং কন্ডেটিংয়ের চেয়ে স্ট্রিংবিল্ডার ব্যবহার করা উচিত।
স্টিফেন সি

ঠিক আছে, আপনি যদি দক্ষতার বিষয়ে পছন্দসই হতে চান তবে একটি স্ট্রিং রাইটার ব্যবহার করুন;)
মিগুয়েল পিং

8

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

Joiner.on(", ").join(34, 26, ..., 2)

এটি বিভিন্ন আরগস, পুনরাবৃত্তিযোগ্য এবং অ্যারে পরিচালনা করে এবং একাধিক চরের বিভাজককে সঠিকভাবে পরিচালনা করে (গিমলের উত্তরের বিপরীতে)। এটি আপনার তালিকার নাল মানগুলি হ্যান্ডেল করবে যদি আপনার প্রয়োজন হয়।


7

এখানে একটি অবিশ্বাস্যভাবে জেনেরিক সংস্করণ যা আমি পূর্ববর্তী পরামর্শগুলির সংমিশ্রণ থেকে তৈরি করেছি:

public static <T> String buildCommaSeparatedString(Collection<T> values) {
    if (values==null || values.isEmpty()) return "";
    StringBuilder result = new StringBuilder();
    for (T val : values) {
        result.append(val);
        result.append(",");
    }
    return result.substring(0, result.length() - 1);
}

7
String.join(", ", collectionOfStrings)

জাভা 8 এপিআই উপলব্ধ।

এর বিকল্প (কোনও গুগল পেয়ারা নির্ভরতা যুক্ত করার প্রয়োজন ছাড়াই):

Joiner.on(",").join(collectionOfStrings);

5

আপনি চেষ্টা করতে পারেন

List collections = Arrays.asList(34, 26, "...", 2);
String asString = collection.toString();
// justValues = "34, 26, ..., 2"
String justValues = asString.substring(1, asString.length()-1);

4

পেয়ারা বা অ্যাপাচি কমন্স ব্যবহার বাদে এটি এখন পর্যন্ত সংক্ষিপ্ত সমাধান হবে

String res = "";
for (String i : values) {
    res += res.isEmpty() ? i : ","+i;
}

0,1 এবং n উপাদান তালিকার সাথে ভাল। তবে আপনাকে নাল তালিকার জন্য পরীক্ষা করতে হবে। আমি এটি জিডব্লিউটিতে ব্যবহার করি, সুতরাং আমি স্ট্রিংবিল্ডার ছাড়াই ভাল good এবং সংক্ষিপ্ত তালিকার জন্য মাত্র দু'একটি উপাদান সহ এটি অন্য কোথাও ঠিক আছে;)


4

সাম্প্রতিক সময়ে কেউ যদি এ নিয়ে হোঁচট খায় তবে আমি জাভা 8 ব্যবহার করে একটি সহজ প্রকরণ যুক্ত করেছি reduce()। এটি অন্যদের দ্বারা ইতিমধ্যে উল্লিখিত কয়েকটি সমাধান অন্তর্ভুক্ত করেছে:

import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.StringUtils;    

import com.google.common.base.Joiner;

public class Dummy {
  public static void main(String[] args) {

    List<String> strings = Arrays.asList("abc", "de", "fg");
    String commaSeparated = strings
        .stream()
        .reduce((s1, s2) -> {return s1 + "," + s2; })
        .get();

    System.out.println(commaSeparated);

    System.out.println(Joiner.on(',').join(strings));

    System.out.println(StringUtils.join(strings, ","));

  }
}


4

আমি মনে করি যে আপনার মতো ক্লজ মানগুলি যেখানে করছেন সেদিকে লক্ষ রেখে স্কেলটি গঠন করা ভাল ধারণা নয়:

SELECT.... FROM.... WHERE ID IN( value1, value2,....valueN)

কোথায় valueXস্ট্রিং একটি তালিকা থেকে আসে।

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

দ্বিতীয়ত, যদি মানগুলি ব্যবহারকারী বা অন্যান্য সিস্টেমের কাছ থেকে আসে তবে একটি এসকিউএল ইঞ্জেকশন আক্রমণ সম্ভব।

এটি অনেক বেশি ভার্বোজ কিন্তু আপনার যা করা উচিত তা হ'ল একটি স্ট্রিং তৈরি করুন:

SELECT.... FROM.... WHERE ID IN( ?, ?,....?)

এবং তারপরে ভেরিয়েবলগুলি বাঁধুন Statement.setString(nParameter,parameterValue)


3

এই সমস্যাটি মোকাবেলার জন্য আরও একটি পদ্ধতি। সর্বাধিক সংক্ষিপ্ত নয়, তবে এটি দক্ষ এবং কাজটি সম্পন্ন করে।

/**
 * Creates a comma-separated list of values from given collection.
 * 
 * @param <T> Value type.
 * @param values Value collection.
 * @return Comma-separated String of values.
 */
public <T> String toParameterList(Collection<T> values) {
   if (values == null || values.isEmpty()) {
      return ""; // Depending on how you want to deal with this case...
   }
   StringBuilder result = new StringBuilder();
   Iterator<T> i = values.iterator();
   result.append(i.next().toString());
   while (i.hasNext()) {
      result.append(",").append(i.next().toString());
   }
   return result.toString();
}

2

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

public static <T> String join(Collection<T> values)
{
    StringBuffer ret = new StringBuffer();
    for (T value : values)
    {
        if (ret.length() > 0) ret.append(",");
        ret.append(value);
    }
    return ret.toString();
}

কালেকশন.টোস্ট্রিং () ব্যবহারের সাথে আরেকটি পরামর্শ সংক্ষিপ্ত, তবে এটি কালেকশন.টোস্ট্রিং () উপর নির্ভর করে খুব নির্দিষ্ট বিন্যাসে একটি স্ট্রিং ফিরিয়ে দেয়, যা আমি ব্যক্তিগতভাবে নির্ভর করতে চাই না।


2

আপনি যদি বসন্ত ব্যবহার করেন তবে আপনি এটি করতে পারেন:

StringUtils.arrayToCommaDelimitedString(
    collectionOfStrings.toArray()
)

(প্যাকেজ org.springframework.util)


1

এটি কতটা "পরিশীলিত" তা আমি নিশ্চিত নই, তবে এটি অবশ্যই খানিকটা খাটো। এটি বিভিন্ন ধরণের সংগ্রহের সাথে কাজ করবে যেমন <ইন্টিজার>, তালিকা <স্ট্রিং> ইত্যাদি সেট করুন with

public static final String toSqlList(Collection<?> values) {

    String collectionString = values.toString();

    // Convert the square brackets produced by Collection.toString() to round brackets used by SQL
    return "(" + collectionString.substring(1, collectionString.length() - 1) + ")";
}

পাঠকের জন্য অনুশীলন : এই পদ্ধতিটি এমনভাবে সংশোধন করুন যাতে এটি শূন্য / ফাঁকা সংগ্রহকে সঠিকভাবে পরিচালনা করে :)


1

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


1

আমি আমার লাইব্রেরি ডলারের জন্য সবেমাত্র একটি পরীক্ষা চেক-ইন করেছি :

@Test
public void join() {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    String string = $(list).join(",");
}

এটি প্রায় তালিকা / অ্যারে / স্ট্রিং জন্য / etc একটি অনর্গল মোড়কের ব্যবহার তৈরি শুধুমাত্র একটি স্ট্যাটিক আমদানি : $

এনবি :

পূর্ববর্তী তালিকা রেঞ্জ হিসাবে ব্যবহার করে আবার লিখতে পারেন $(1, 5).join(",")


1

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

এটি কৌশলটি করবে, এটি কী করছে তা সুস্পষ্ট এবং কোনও বাহ্যিক গ্রন্থাগারের উপর নির্ভর করে না:

StringBuffer inString = new StringBuffer(listOfIDs.get(0).toString());
for (Long currentID : listOfIDs) {
  inString.append(",").append(currentID);
}

1

যদিও আমি মনে করি আপনার সেরা বাজিটি পেয়ারা থেকে জেন্ডার ব্যবহার করা, যদি আমি এটি হাত দিয়ে কোড করি তবে আমি এই পদ্ধতিকে আরও মার্জিত বলে মনে করি যে 'প্রথম' পতাকাটি বা শেষ কমাটি কাটা।

private String commas(Iterable<String> strings) {
    StringBuilder buffer = new StringBuilder();
    Iterator<String> it = strings.iterator();
    if (it.hasNext()) {
        buffer.append(it.next());
        while (it.hasNext()) {
            buffer.append(',');
            buffer.append(it.next());
        }
    }

    return buffer.toString();
}


1

আমি এখানে যা দেখছি তার ভিত্তিতে আরেকটি বিকল্প (সামান্য পরিবর্তন সহ)।

public static String toString(int[] numbers) {
    StringBuilder res = new StringBuilder();
    for (int number : numbers) {
        if (res.length() != 0) {
            res.append(',');
        }
        res.append(number);
    }
    return res.toString();
}

1

যোগ দিন 'পদ্ধতি' অ্যারে এবং ক্লাসগুলিতে পাওয়া যায় যা প্রসারিত হয় AbstractCollectionsতবে toString()পদ্ধতিটি ওভাররাইড করে না (কার্যত সমস্ত সংগ্রহের মতোjava.util )।

এই ক্ষেত্রে:

String s= java.util.Arrays.toString(collectionOfStrings.toArray());
s = s.substing(1, s.length()-1);// [] are guaranteed to be there

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


1
List<String> collectionOfStrings = // List of string to concat
String csvStrings = StringUtils.collectionToDelimitedString(collectionOfStrings, ",");

স্প্রিংফ্রেমোউর্ক থেকে স্ট্রিংইটিলস: স্প্রিং-কোর


0

আপনি লিনকিউ (এসকিউএল) ব্যবহার করতে পারবেন, এবং আপনি এমএস থেকে ডায়নামিক কোয়েরি লিনকিউ নমুনাটি ব্যবহার করতে সক্ষম হতে পারেন। http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1- using-the-linq-dynamic-query-library.aspx


0
java.util.List<String> lista = new java.util.ArrayList<String>();
lista.add("Hola");
lista.add("Julio");
System.out.println(lista.toString().replace('[','(').replace(']',')'));

$~(Hola, Julio)

4
এটি একটি খারাপ অভ্যাস। টসস্ট্রিং বাস্তবায়ন পরিবর্তিত হয় এমন অনুমান আপনি করতে পারবেন না।
ড্রিঙ্ক্ট

0
String commaSeparatedNames = namesList.toString().replaceAll( "[\\[|\\]| ]", "" );  // replace [ or ] or blank

স্ট্রিং উপস্থাপনায় সংগ্রহের উপাদানগুলির একটি তালিকা রয়েছে যাতে তারা এর পুনরুক্তকারী দ্বারা বর্গাকার বন্ধনী ("[]") দ্বারা আবদ্ধ ক্রমে ফিরে আসে। সংলগ্ন উপাদানগুলি "," (কমা এবং স্পেস) অক্ষর দ্বারা পৃথক করা হয়।

বিমূর্ত সংগ্রহ সংগ্রহ javadoc


0

তালিকা টোকেন = নতুন অ্যারেলিস্ট (ফলাফল); ফাইনাল স্ট্রিংবিল্ডার বিল্ডার = নতুন স্ট্রিংবিল্ডার ();

    for (int i =0; i < tokens.size(); i++){
        builder.append(tokens.get(i));
        if(i != tokens.size()-1){
            builder.append(TOKEN_DELIMITER);
        }
    }

builder.toString ();

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