পাইথন ব্যবহার করে স্ট্রিং থেকে অঙ্কগুলি বাদে অক্ষরগুলি সরাবেন?


137

আমি স্ট্রিং থেকে সংখ্যা বাদে সমস্ত অক্ষরকে কীভাবে সরিয়ে ফেলতে পারি?


@ জান তোজনার: আপনি একটি উদাহরণ দিতে পারেন?
জোও সিলভা

@ জিজি: আমার কাছে জিটিকে.এন্ট্রি () আছে এবং আমি এতে বহুগুণ ভাসমান প্রবেশ করতে চাই।
জান তোজনার

1
@ জনটোজানর উত্তর দুটি অনুসারে পুনঃসুব পদ্ধতিটি ব্যবহার করে এবং স্পষ্টভাবে কোন অক্ষরগুলি রাখার জন্য তা অবশ্যই তালিকাভুক্ত করে re উদাহরণস্বরূপ re.sub ("[^ 0123456789]।]", "", "Poo123.4and5fish")
রজার হিথকোট

উত্তর:


112

পাইথন ২. * এ এখন পর্যন্ত সবচেয়ে দ্রুত পদ্ধতির .translateপদ্ধতি:

>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>> 

string.maketransএকটি অনুবাদ টেবিল তৈরি করে (দৈর্ঘ্যের 256 দৈর্ঘ্যের একটি স্ট্রিং) যা এই ক্ষেত্রে একই ''.join(chr(x) for x in range(256))(এটি তৈরি করতে কেবল দ্রুত ;-))। .translateঅনুবাদ টেবিল প্রয়োগ করে (যা এখানে অপ্রাসঙ্গিক যেহেতু allমূলত পরিচয় বোঝায়) এবং দ্বিতীয় যুক্তিতে উপস্থিত অক্ষরগুলি মুছে দেয় - মূল অংশ।

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

২. এ ফিরে যান, পারফরম্যান্সের পার্থক্যটি চিত্তাকর্ষক ...:

$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"' 'x.translate(all, nodig)'
1000000 loops, best of 3: 1.04 usec per loop
$ python -mtimeit -s'import re;  x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 7.9 usec per loop

জিনিসগুলি 7-8 বার বাড়িয়ে দেওয়া খুব কমই চিনাবাদাম, সুতরাং translateপদ্ধতিটি জানার এবং ব্যবহারের পক্ষে উপযুক্ত। অন্যান্য জনপ্রিয় নন-আরআর পদ্ধতির ...:

$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop

আরই এর চেয়ে 50% ধীর গতির, তাই .translateপদ্ধতির আকারটি এটি বাড়িয়ে তোলে।

পাইথন 3 এ, বা ইউনিকোডের জন্য আপনাকে এমন .translateএকটি ম্যাপিং পাস করতে হবে (অর্ডিনালগুলি সহ, সরাসরি কী হিসাবে অক্ষর নয়) যা Noneআপনি মুছতে চান তার জন্য ফিরে আসে । "সমস্ত কিছু কিন্তু" কয়েকটি অক্ষর মুছে ফেলার জন্য এটি প্রকাশ করার জন্য এখানে একটি সুবিধাজনক উপায়:

import string

class Del:
  def __init__(self, keep=string.digits):
    self.comp = dict((ord(c),c) for c in keep)
  def __getitem__(self, k):
    return self.comp.get(k)

DD = Del()

x='aaa12333bb445bb54b5b52'
x.translate(DD)

এছাড়াও নির্গত হয় '1233344554552'। তবে এটি xx.py এ রাখছি ...:

$ python3.1 -mtimeit -s'import re;  x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 8.43 usec per loop
$ python3.1 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
10000 loops, best of 3: 24.3 usec per loop

... যা দেখায় যে এই ধরণের "মুছে ফেলা" কাজের জন্য পারফরম্যান্স সুবিধাটি অদৃশ্য হয়ে যায় এবং একটি কার্যকারিতা হ্রাস হয়ে যায়।


1
@ সুনকিয়াং, হ্যাঁ, একেবারে - এর কারণ আছে যে পাই 3k ইউনিকোডে টেক্সট স্ট্রিং টাইপ হিসাবে গেছে, পাই 2 এর মতো বাইট স্ট্রিংয়ের পরিবর্তে - জাভা এবং সি # সর্বদা একই "স্ট্রিং মানে ইউনিকোড" মেম আছে ... কিছু ওভারহেড, সম্ভবত, তবে কেবল ইংরাজী ব্যতীত অন্য কোনও কিছুর জন্য আরও বেশি সমর্থন করা উচিত! -)।
অ্যালেক্স মার্টেলি

29
x.translate(None, string.digits)প্রকৃতপক্ষে ফলাফল 'aaabbbbbb', যা যা উদ্দেশ্য এর বিপরীত।
টম ডালিং

4
টম ডালিংয়ের মন্তব্য প্রতিধ্বনিত করা, আপনার প্রথম উদাহরণটি সমস্ত অনাকাঙ্ক্ষিত চরিত্র রাখে - আপনি যা বলেছিলেন তার বিপরীতে থাকে।
ক্রিস জনসন

3
@ রায়ানবি.লিনচ এট আল, দোষটি পরবর্তী সম্পাদক এবং অন্য দু'জন ব্যবহারকারীকে দিয়েছিল যা সম্পাদনা অনুমোদন করেছে , যা আসলে সম্পূর্ণ ভুল। প্রত্যাবর্তিত।
নিক টি

1
ওভাররাইডিং allবিল্টিন ... এটি সম্পর্কে নিশ্চিত নয়!
অ্যান্ডি হেডেন

197

re.subযেমন ব্যবহার করুন :

>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'

\D কোনও অ-অঙ্কের অক্ষরের সাথে মেলে তাই উপরের কোডটি মূলত প্রতিটি অ-অঙ্কের অক্ষরকে খালি স্ট্রিংয়ের জন্য প্রতিস্থাপন করবে।

অথবা আপনি filterযেমন ব্যবহার করতে পারেন (পাইথন 2 তে):

>>> filter(str.isdigit, 'aas30dsa20')
'3020'

পাইথন 3 এ, এর filterপরিবর্তে একটি পুনরাবৃত্তি প্রদান করে list, পরিবর্তে আপনি নিম্নলিখিতটি ব্যবহার করতে পারেন:

>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'

পুনরায় এ জাতীয় সহজ কাজটিতে দুষ্ট, দ্বিতীয়টি আমার মনে হয় সবচেয়ে ভাল, কারণ 'হল ...' পদ্ধতিগুলি স্ট্রিংয়ের জন্য দ্রুততম।
f0b0s

আপনার ফিল্টার উদাহরণ পিআই 2 কে
সিলেন্টগোস্টে

2
@ f0b0s-iu9- তথ্য: আপনি এটির সময়সীমা করেছেন? আমার মেশিনে (পাইক 3 কে) ফিল্টারের তুলনায় দ্বিগুণ দ্রুত isdigit, জেনারেটর isdigtতাদের মধ্যে অর্ধেক পথ
সাইলেন্টঘস্ট

@ সাইলেন্টগোস্ট: ধন্যবাদ, আমি পাই 2 কে আইডিএল ব্যবহার করছিলাম। এটি এখন স্থির।
জোও সিলভা

1
@ এ্যাসমায়ার কেবল rকাঁচা স্ট্রিংয়ের জন্য ব্যবহার করুন :re.sub(r"\D+", "", "aas30dsa20")
মিচ ম্যাকম্যাবার্স


17

আপনি ফিল্টার ব্যবহার করতে পারেন:

filter(lambda x: x.isdigit(), "dasdasd2313dsa")

পাইথন ৩.০ এ আপনাকে যোগ দিতে হবে (কুরুচিপূর্ণ :()

''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))

কেবল পাই 2 কে, পাই 3 কে এটি জেনারেটর ফিরিয়ে দেয়
সাইলেন্টগোস্ট

রূপান্তর strকরার listনিশ্চিত এটি উভয় py2 এবং py3 উপর কাজ করে করতে:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
লুইজ সি

13

বায়ের উত্তরের লাইন বরাবর:

''.join(i for i in s if i.isdigit())

না, এটি নেতিবাচক সংখ্যার জন্য কাজ করবে না কারণ -একটি সংখ্যা নয়।
অলি

12

আপনি এটি সহজেই রেজিक्स ব্যবহার করে করতে পারেন

>>> import re
>>> re.sub("\D","","£70,000")
70000

এখন পর্যন্ত সবচেয়ে সহজ উপায়
আয়রেক

5
এটি ã বছর আগে সরবরাহ করা জোয়াও সিলভার উত্তর থেকে কীভাবে আলাদা?
jww

7
x.translate(None, string.digits)

স্ট্রিং থেকে সমস্ত অঙ্ক মুছে ফেলা হবে। বর্ণগুলি মুছতে এবং অঙ্কগুলি রাখতে, এটি করুন:

x.translate(None, string.letters)

3
আমি একটি পেয়েছি TypeError: অনুবাদ () ঠিক একটি যুক্তি নেয় (2 দেওয়া)। কেন এই প্রশ্নটির বর্তমান অবস্থায় এটি উত্থাপিত হয়েছিল তা হতাশাব্যঞ্জক।
বোবার্ট

পাইথন 2 থেকে অনুবাদ 3 এ পরিবর্তিত হয়েছে। পাইথন 3-এ এই পদ্ধতিটি ব্যবহার করে সিনট্যাক্স হ'ল x.translate (str.maketrans ('', '', স্ট্রিং। ডিজিটস)) এবং x.translate (str.maketrans ('', '') , string.ascii_letters))। এই স্ট্রিপগুলির কোনওটিই সাদা স্থান নয়। আমি আর এই পদ্ধতির সত্যিই সুপারিশ করব না ...
ZaxR

5

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

>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'

"Poo123.4 and.5.5" সম্পর্কে কী?
জান তোজনার

আমার কোডে আমি ইনপুট স্ট্রিংয়ে পিরিয়ডের সংখ্যাটি যাচাই করি এবং যদি এটি 1 এর বেশি হয় তবে একটি ত্রুটি উত্থাপন করি
রজার হিথকোট

4

পাইথন 3 এর একটি দ্রুত সংস্করণ:

# xx3.py
from collections import defaultdict
import string
_NoneType = type(None)

def keeper(keep):
    table = defaultdict(_NoneType)
    table.update({ord(c): c for c in keep})
    return table

digit_keeper = keeper(string.digits)

এখানে একটি পারফরম্যান্স তুলনা বনাম রেজেক্স:

$ python3.3 -mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"' 'x.translate(xx3.digit_keeper)'
1000000 loops, best of 3: 1.02 usec per loop
$ python3.3 -mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"' 'r.sub("", x)'
100000 loops, best of 3: 3.43 usec per loop

সুতরাং এটি আমার কাছে রেজেক্সের চেয়ে 3 গুণ বেশি দ্রুত। এটি class Delউপরের থেকেও দ্রুত , কারণ defaultdictপাইথনের (ধীর) পরিবর্তে এর সমস্ত লুক সি আছে in তুলনা করার জন্য, এই একই সংস্করণটি আমার একই সিস্টেমে।

$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop

3

একটি জেনারেটর এক্সপ্রেশন ব্যবহার করুন:

>>> s = "foo200bar"
>>> new_s = "".join(i for i in s if i in "0123456789")

পরিবর্তে করুন''.join(n for n in foo if n.isdigit())
shxfi

2

কুরুচিপূর্ণ কিন্তু কাজ করে:

>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>

তুমি কেন করো list(s)?
সাইলেন্টগোস্ট

@ সাইলেন্টগোস্ট এটি আমার ভুল বোঝাবুঝি। এটা ধন্যবাদ :) সঠিক
Gant

আসলে, এই পদ্ধতিটি সহ, আমি আপনাকে "যোগদান" ব্যবহার করার প্রয়োজন বলে মনে করি না। filter(lambda x: x.isdigit(), s)আমার জন্য ভাল কাজ করে। ... ওহ, কারণ আমি পাইথন ২.7 ব্যবহার করছি।
ববোর্ট

1
$ python -mtimeit -s'import re;  x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'

100000 লুপ, প্রতি লুপে 3: 2.48 ইউএসসি সেরা

$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'

100000 লুপ, 3 লুপের প্রতি সেরা: 2.02 ইউজেক

$ python -mtimeit -s'import re;  x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'

100000 লুপ, প্রতি লুপে 3: 2.37 ইউজেকের সেরা

$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'

100000 লুপ, 3 লুপ প্রতি 1.97 ইউএসসি সেরা

আমি দেখেছি যে যোগদানের সাব চেয়ে দ্রুত।


কেন আপনি দুটি পদ্ধতি পুনরায় পুনরাবৃত্তি করছেন? এবং আপনি কীভাবে বর্ণনা করতে পারবেন যে আপনার উত্তর গৃহীত উত্তর থেকে আলাদা কীভাবে?
জান তোজনার

উভয় একই আউটপুট ফলাফল। তবে, আমি কেবল দেখাতে চাই যে ফলাফলগুলিতে সাব-মেথডটি দ্রুততর হয় join
অনিলরেডি

তারা না করে, আপনার কোডটি বিপরীত করে। এবং আপনার চারটি পরিমাপ রয়েছে তবে দুটি পদ্ধতি রয়েছে।
জান তোজনার

1

আপনি প্রতিটি চরিত্র পড়তে পারেন। যদি এটি অঙ্ক হয় তবে উত্তরে এটি অন্তর্ভুক্ত করুন। str.isdigit() পদ্ধতি একটি উপায় যদি একটি অক্ষর অঙ্ক জানি হয়।

your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'

এটি f0b0 দ্বারা উত্তর থেকে কীভাবে আলাদা? এর পরিবর্তে আপনার উত্তরটি সম্পাদনা করা উচিত যদি আপনার কাছে আরও তথ্য আনতে হয়
শেভিবো

0

এক লাইনার নয় তবে খুব সাধারণ:

buffer = ""
some_str = "aas30dsa20"

for char in some_str:
    if not char.isdigit():
        buffer += char

print( buffer )

0

আমি এই ব্যবহার। 'letters'আপনি যে সমস্ত অক্ষর থেকে পরিত্রাণ পেতে চান সেগুলিতে এমন হওয়া উচিত:

Output = Input.translate({ord(i): None for i in 'letters'}))

উদাহরণ:

Input = "I would like 20 dollars for that suit" Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'})) print(Output)

আউটপুট: 20

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