অভিধানের মতো তালিকার কেন নিরাপদ "পান" পদ্ধতি নেই?


264

কেন তালিকার মতো অভিধানের মতো নিরাপদ "get" পদ্ধতি নেই?

>>> d = {'a':'b'}
>>> d['a']
'b'
>>> d['c']
KeyError: 'c'
>>> d.get('c', 'fail')
'fail'

>>> l = [1]
>>> l[10]
IndexError: list index out of range

1
তালিকা অভিধানের তুলনায় বিভিন্ন উদ্দেশ্যে ব্যবহৃত হয়। তালিকার সাধারণ ব্যবহারের ক্ষেত্রে গেট () দরকার হয় না। তবে অভিধানের জন্য গেট () প্রায়শই দরকারী।
ম্যাগগ্রোনবার

42
আপনি যদি এর পরিবর্তে কোনও স্লাইস চেয়ে থাকেন তবে উদাহরণস্বরূপ, l[10:11]পরিবর্তে সূচিপত্র না বাড়িয়ে আপনি তালিকার বাইরে সর্বদা একটি খালি সাবলিস্ট পেতে পারেন l[10]। () সাবলিস্টে উপস্থিত থাকলে কাঙ্ক্ষিত উপাদান থাকবে)
jsbueno

56
কিছু এখানে বিপরীতে, আমি একটি নিরাপদ ধারণা সমর্থন করি .get। এটি সমান l[i] if i < len(l) else default, তবে আরও পঠনযোগ্য, আরও সংক্ষিপ্ত এবং iএটি পুনরায় গণনা না করেই একটি অভিব্যক্তি হওয়ার অনুমতি দেবে
পল ড্রাগার

6
আজ আমি এই অস্তিত্ব কামনা। আমি একটি ব্যয়বহুল ফাংশন ব্যবহার করি যা একটি তালিকা প্রত্যাবর্তন করে তবে আমি কেবল প্রথম আইটেমটি চেয়েছিলাম, বা Noneযদি এটি উপস্থিত না থাকে। এটি বললে ভাল লাগত x = expensive().get(0, None)তাই আমাকে ব্যয়বহুল রিটার্ন অস্থায়ী ভেরিয়েবলের মধ্যে ফেলতে হবে না।
রায়ান হাইবার্ট

2
@Ryan আমার উত্তর সাহায্য করতে পারে আপনি stackoverflow.com/a/23003811/246265
জেক

উত্তর:


112

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

অবশ্যই আপনি সহজেই এটিকে প্রয়োগ করতে পারেন:

def safe_list_get (l, idx, default):
  try:
    return l[idx]
  except IndexError:
    return default

এমনকি আপনি সম্মুখের দিকে এটি monkeypatch পারে __builtins__.listমধ্যে কন্সট্রাকটর __main__, কিন্তু যেহেতু সবচেয়ে কোড ব্যবহার করে না যে একটি কম পরিব্যাপক পরিবর্তন হতে পারে। আপনি যদি কেবল নিজের কোড দ্বারা তৈরি তালিকাগুলি দিয়ে এটি ব্যবহার করতে চান তবে আপনি কেবল সাবক্লাস listএবং getপদ্ধতিটি যুক্ত করতে পারেন ।


24
পাইথন মনকিপ্যাচিংয়ের মতো বিল্টিন টাইপের মঞ্জুরি দেয় নাlist
ইমরান

7
@ সিএসজেড: .getতালিকাগুলির মধ্যে থাকা সমস্যাটি সমাধান করে - অস্তিত্ব না থাকা ডেটা পাওয়ার সময় ব্যতিক্রম এড়ানোর কার্যকর উপায়। বৈধ তালিকা সূচক কী তা জানার পক্ষে এটি অত্যন্ত তুচ্ছ এবং খুব দক্ষ, তবে অভিধানের মূল মানগুলির জন্য এটি করার বিশেষ কোনও ভাল উপায় নেই।
নিক বেস্টিন

10
আমি মোটেও দক্ষতার বিষয়ে মনে করি না - কোনও অভিধানে কোনও কী উপস্থিত রয়েছে এবং / অথবা কোনও আইটেম ফিরিয়ে দিচ্ছে কিনা তা পরীক্ষা করা O(1)। এটা তোলে পরীক্ষণ যেমন কাঁচা পরিপ্রেক্ষিতে বেশ দ্রুত হিসাবে হবে না len, কিন্তু একটা দৃশ্য জটিলতা বিন্দু থেকে তারা সব করছি O(1)। সঠিক উত্তরটি হ'ল সাধারণ ব্যবহার / শব্দার্থক এক ...
মার্ক লংগায়ার

3
@ মার্ক: সমস্ত ও (1) সমান তৈরি হয় না। এছাড়াও, dictকেবলমাত্র সেরা কেস (1), সমস্ত ক্ষেত্রে নয়।
নিক বেস্টিন

4
আমি মনে করি যে লোকেরা এখানে পয়েন্টটি মিস করছে। দক্ষতা সম্পর্কে আলোচনা হওয়া উচিত নয়। অকাল অপটিমাইজেশন সঙ্গে বন্ধ করুন। যদি আপনার প্রোগ্রামটি খুব মন্থর হয় তবে আপনি হয় আপত্তি করছেন .get()বা আপনার কোডে (বা পরিবেশ) অন্য কোথাও সমস্যা আছে। এই জাতীয় পদ্ধতি ব্যবহারের বিষয়টি হ'ল কোড পঠনযোগ্যতা। "ভ্যানিলা" কৌশলটিতে প্রতিটি জায়গায় চারটি লাইন কোডের প্রয়োজন যা এটি করা দরকার। .get()কৌশল মাত্র এক প্রয়োজন এবং সহজে পরবর্তী পদ্ধতি কল (যেমন সঙ্গে শৃঙ্খলিত করা যেতে পারে my_list.get(2, '').uppercase())।
টাইলার ক্রম্পটন

66

আপনি যদি প্রথম উপাদানটি পছন্দ করেন তবে এটি কাজ করে my_list.get(0)

>>> my_list = [1,2,3]
>>> next(iter(my_list), 'fail')
1
>>> my_list = []
>>> next(iter(my_list), 'fail')
'fail'

আমি জানি আপনি ঠিক যা চেয়েছিলেন তা নয় তবে এটি অন্যকে সাহায্য করতে পারে।


7
ফাংশনাল প্রোগ্রামিং-এস্কের চেয়ে অজগরটি কম
এরিক

next(iter(my_list[index:index+1]), 'fail')কোনো সূচির জন্য অনুমতি দেয়, শুধু 0. বা কম FP কিন্তু তর্কসাপেক্ষে আরো Pythonic, এবং প্রায় অবশ্যই আরো পাঠযোগ্য: my_list[index] if index < len(my_list) else 'fail'
বর্ণমালা

47

সম্ভবত কারণ এটি শব্দার্থবিজ্ঞানের তালিকাটির জন্য খুব বেশি অর্থ দেয়নি। তবে আপনি সাবক্লাসিং করে সহজেই নিজের তৈরি করতে পারেন।

class safelist(list):
    def get(self, index, default=None):
        try:
            return self.__getitem__(index)
        except IndexError:
            return default

def _test():
    l = safelist(range(10))
    print l.get(20, "oops")

if __name__ == "__main__":
    _test()

5
এটি এখন পর্যন্ত, ওপিকে সবচেয়ে উত্তর দিচ্ছে p মনে রাখবেন যে আপনি একটি সাবলিস্টও বের করতে পারেন যা পাইথনের নিরাপদ অপারেশন। মাইলিস্ট দেওয়া = [1, 2, 3], আপনি কোনও ব্যতিক্রম ট্রিগার না করে মাইলিস্ট [8: 9] এর সাথে নবম উপাদানটি বের করার চেষ্টা করতে পারেন। তারপরে আপনি তালিকাটি খালি রয়েছে কিনা তা পরীক্ষা করতে পারেন এবং যদি এটি খালি না হয় তবে ফিরে আসা তালিকা থেকে একক উপাদানটি বের করুন।
jose.angel.jimenez

1
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত, অন্যান্য অ-পাইথোনিক ওয়ান-লাইন হ্যাক নয়, বিশেষত কারণ এটি অভিধান সহ প্রতিসাম্য সংরক্ষণ করে।
এরিক

1
আপনার নিজস্ব তালিকা সাবক্লাসিংয়ের জন্য পাইথনিকের কিছু নেই কারণ আপনার প্রয়োজন একটি দুর্দান্ত getপদ্ধতি। পঠনযোগ্যতা গণনা। এবং পাঠ্যতা প্রতিটি অতিরিক্ত অপ্রয়োজনীয় শ্রেণীর সাথে ভোগে। try / exceptসাবক্ল্যাস তৈরি না করে কেবল অ্যাপ্রোচ ব্যবহার করুন ।
জিয়েকোমন 8

@ জিয়েকোমন সাবক্লাসিং করে বয়লারপ্লেট হ্রাস করার জন্য এটি পুরোপুরি পাইথোনিক।
কিথ

42

.Get ব্যবহারের পরিবর্তে, এই জাতীয় ব্যবহার করা তালিকার জন্য ঠিক হওয়া উচিত। কেবল একটি ব্যবহারের পার্থক্য।

>>> l = [1]
>>> l[10] if 10 < len(l) else 'fail'
'fail'

15
আমরা -1 দিয়ে সর্বশেষতম উপাদানটি পেতে চেষ্টা করলে এটি ব্যর্থ হয়।
pretobomba

নোট করুন যে এটি বিজ্ঞপ্তিযুক্ত লিঙ্কযুক্ত তালিকার অবজেক্টগুলির জন্য কাজ করে না। অতিরিক্তভাবে, সিনট্যাক্সের কারণে আমি "স্ক্যানিং ব্লক" বলতে পছন্দ করি causes কোডটি স্ক্যান করার সময় এটি কী করে তা দেখার জন্য, এটি এমন একটি লাইন যা আমাকে এক মুহুর্তের জন্য ধীর করে দেয়।
টাইলার ক্রম্পটন

ইনলাইন যদি / অন্যথায় ২.6 এর মতো পুরানো অজগর দিয়ে কাজ না করে (বা এটি 2.5?)
এরিক

3
@ টাইলারক্রম্পটন: পাইথনে কোনও বিজ্ঞপ্তিযুক্ত লিঙ্ক নেই। আপনি যদি নিজে নিজে একটি লিখে থাকেন তবে আপনি কোনও .getপদ্ধতি প্রয়োগ করতে পারেন নিচে (আমি নিশ্চিত নই যে আপনি এই ক্ষেত্রে সূচকটি কী বোঝাতে চেয়েছিলেন বা কেন এটি কখনও ব্যর্থ হবে) not
নিক বেস্টিন

একটি বিকল্প যে আউট-অফ-বাউন্ড হ্যান্ডলগুলি নেতিবাচক সূচকের হবেlst[i] if -len(lst) <= i < len(l) else 'fail'
মাইক

17

এটা চেষ্টা কর:

>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'

1
আমি এটি পছন্দ করি যদিও এর জন্য প্রথমে একটি নতুন উপ-তালিকা তৈরি করা দরকার।
রিক

15

Jose.angel.jimenez এর ক্রেডিট


"অনেলিনার" ভক্তদের জন্য ...


আপনি যদি তালিকার প্রথম উপাদানটি চান বা যদি ডিফল্ট মান চান তবে তালিকাটি খালি চেষ্টা করুন:

liste = ['a', 'b', 'c']
value = (liste[0:1] or ('default',))[0]
print(value)

আয় a

এবং

liste = []
value = (liste[0:1] or ('default',))[0]
print(value)

আয় default


অন্যান্য উপাদানগুলির উদাহরণ ...

liste = ['a', 'b', 'c']
print(liste[0:1])  # returns ['a']
print(liste[1:2])  # returns ['b']
print(liste[2:3])  # returns ['c']

ডিফল্ট ফ্যালব্যাক সহ…

liste = ['a', 'b', 'c']
print((liste[0:1] or ('default',))[0])  # returns a
print((liste[1:2] or ('default',))[0])  # returns b
print((liste[2:3] or ('default',))[0])  # returns c

পরীক্ষিত Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)


1
সংক্ষিপ্ত বিকল্প: value, = liste[:1] or ('default',)। দেখে মনে হচ্ছে আপনার প্রথম বন্ধনী দরকার।
qräbnö

13

আপনি যা করতে পারেন তার মধ্যে সেরা কাজটি হ'ল তালিকাকে একটি ডিকে রূপান্তর করা এবং তারপরে গেট পদ্ধতির মাধ্যমে এটি অ্যাক্সেস করা:

>>> my_list = ['a', 'b', 'c', 'd', 'e']
>>> my_dict = dict(enumerate(my_list))
>>> print my_dict
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
>>> my_dict.get(2)
'c'
>>> my_dict.get(10, 'N/A')

20
একটি যুক্তিসঙ্গত কাজ, কিন্তু খুব কমই "আপনি করতে পারেন সেরা জিনিস"।
ট্রিপলি

3
যদিও খুব অদক্ষ। দ্রষ্টব্য: এই zip range lenজিনিসটির পরিবর্তে , কেউ কেবল ব্যবহার করতে পারেdict(enumerate(my_list))
মেরিয়ান

3
এটি সেরা জিনিস নয়, এটি আপনি সবচেয়ে খারাপ কাজ করতে পারেন।
এরিকবার্ক

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

7

সুতরাং আমি এটি সম্পর্কে আরও কিছু গবেষণা করেছি এবং এটি সুনির্দিষ্ট কিছু নেই এর জন্য সুনির্দিষ্ট কিছু নেই। আমি list.index (মান) খুঁজে পেয়ে উত্তেজিত হয়েছি, এটি নির্দিষ্ট আইটেমের সূচকটি ফিরিয়ে দেয়, তবে নির্দিষ্ট সূচীতে মান পাওয়ার জন্য কিছুই নেই। সুতরাং আপনি যদি সেফ_লিস্ট_জেট সমাধানটি ব্যবহার করতে না চান তবে আমার মনে হয় এটি বেশ ভাল। দৃশ্যের উপর নির্ভর করে আপনার জন্য কাজটি সম্পন্ন করতে পারে এমন বিবৃতি যদি এখানে 1 টি লাইনার থাকে:

>>> x = [1, 2, 3]
>>> el = x[4] if len(x) > 4 else 'No'
>>> el
'No'

আপনি 'না' এর পরিবর্তে আর কিছুই ব্যবহার করতে পারবেন না, যা আরও অর্থবোধ করে:

>>> x = [1, 2, 3]
>>> i = 2
>>> el_i = x[i] if len(x) == i+1 else None

এছাড়াও আপনি যদি তালিকার প্রথম বা শেষ আইটেমটি পেতে চান তবে এটি কাজ করে

end_el = x[-1] if x else None

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

def list_get(l, i):
    try:
        return l[i]
    except IndexError:
        return None

দ্রুততম কি তা দেখার জন্য বেঞ্চমার্ক করা হয়নি।


1
আসলেই পাইথোনিক নয়।
এরিক

@ এরিক কোন স্নিপেট? আমি মনে করি চেষ্টাটি ব্যতীত এটি আবার দেখার মাধ্যমে সার্থক করে তোলে।
র‌্যাডটেক

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

1
@ এরিক আমি প্রশ্নটিকে ওওপি-নির্দিষ্ট হিসাবে পার্স না করে তবে "তালিকাগুলি dict.get()ধরার পরিবর্তে তালিকার সূচী রেফারেন্স থেকে কোনও ডিফল্ট মান ফিরিয়ে আনার জন্য কোন উপমা রাখবে না IndexError? সুতরাং এটি সত্যই ভাষা / গ্রন্থাগারের বৈশিষ্ট্য সম্পর্কে (এবং ওওপি নয়) বনাম এফপি প্রসঙ্গ) .এছাড়া, আপনার সম্ভবত 'পাইথোনিক' ব্যবহারের যোগ্যতা অর্জন করতে হবে সম্ভবত ডাব্লুডাব্লুজিডি (এফপি পাইথনের প্রতি তার ঘৃণা সর্বজনবিদিত) এবং কেবল পিইপি 8/20 কে সন্তুষ্ট নয়।
কাওবার্ট

1
el = x[4] if len(x) == 4 else 'No'- মানে len(x) > 4? x[4]সীমার বাইরে যদি হয় len(x) == 4
mic

4

শব্দকোষ চেহারা আপ জন্য। কোনও এন্ট্রি রয়েছে কিনা তা জিজ্ঞাসা করা বুদ্ধিমানের কাজ করে। তালিকাগুলি সাধারণত পুনরাবৃত্তি হয়। L [10] উপস্থিত আছে কিনা তা জিজ্ঞাসা করা সাধারণ নয় তবে L এর দৈর্ঘ্য 11 হয় কিনা।


হ্যাঁ, আপনার সাথে একমত তবে আমি কেবল পৃষ্ঠার "/ গোষ্ঠী / পৃষ্ঠা_নাম" এর সম্পর্কিত ইউআরএল পার্স করেছি। এটি '/' দ্বারা বিভক্ত করুন এবং পৃষ্ঠা নাম নির্দিষ্ট পৃষ্ঠার সমান কিনা তা পরীক্ষা করতে চেয়েছিলেন। দৈর্ঘ্যের জন্য অতিরিক্ত চেক বা ব্যতিক্রম ধরা বা নিজের ফাংশন লেখার পরিবর্তে [url.split ('/') এর মতো কিছু লিখতে আরামদায়ক হবে get get_from_index (2, কিছুই নয়) == "লালা”। সম্ভবত আপনি ঠিক বলেছেন এটিকে কেবল অস্বাভাবিক বলে মনে করা হয়। যাইহোক আমি এখনও এর সাথে একমত নই =)
সিএসজেড

@ নিক বেস্টিন: কিছু ভুল হয়নি। এগুলি কোডিংয়ের সরলতা এবং গতি সম্পর্কে।
সিএসজেড

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

-1

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

আপনি এটি বলতে পারেন: অভিধানগুলিতে আমার প্রায়শই .get () প্রয়োজন। পুরো সময়ের প্রোগ্রামার হিসাবে দশ বছর পরে আমার মনে হয় না যে এটির কোনও তালিকায় আমার কখনও প্রয়োজন ছিল। :)


মন্তব্যগুলিতে আমার উদাহরণ সম্পর্কে কীভাবে? আরও সহজ এবং পাঠযোগ্য কি? (url.split ('/')। getFromIndex (2) == "লালালা") বা (ফলাফল = url.split (); লেন (ফলাফল)> 2 এবং ফলাফল [2] == "লালা")। এবং হ্যাঁ, আমি জানি আমি এই জাতীয় ফাংশনটি নিজেই লিখতে পারি =) তবে আমি অবাক হয়েছি যে এই ধরনের ফাংশনটি অন্তর্নির্মিত নয়।
সিএসজেড

1
আইডি আপনার ক্ষেত্রে বলুন যে আপনি এটি ভুল করছেন। ইউআরএল হ্যান্ডলিং রুট (প্যাটার্ন মেলানো) বা অবজেক্ট ট্রভারসাল দ্বারা করা উচিত। কিন্তু, আপনার নির্দিষ্ট ক্ষেত্রে উত্তর দিতে: 'lalala' in url.split('/')[2:]। তবে আপনার সমাধানের সাথে এখানে সমস্যাটি হ'ল আপনি কেবল দ্বিতীয় উপাদানটির দিকে তাকান। ইউআরএল যদি '/ বানরবোনকি / লালা' হয় তবে কী হবে? Trueইউআরএল অবৈধ হলেও আপনি একটি পাবেন ।
লেনার্ট রেজেব্রো

আমি মাত্র দ্বিতীয় উপাদানটি গ্রহণ করেছি কারণ আমার কেবল দ্বিতীয় উপাদানটির প্রয়োজন। তবে হ্যাঁ, স্লাইসগুলি ভাল কাজের বিকল্প বলে মনে হচ্ছে
CSZ

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