সদৃশ অক্ষরগুলির সাথে ম্যাচটি সরিয়ে ফেলুন: একাধিক (3+) অবিচ্ছিন্ন ঘটনাগুলি প্রতিস্থাপন করুন


9

আমি এমন একটি regexপ্যাটার্ন খুঁজছি যা প্রতিটি চরিত্রের তৃতীয়, চতুর্থ, ... এর সাথে মিলবে। স্পষ্টতার জন্য নীচে দেখুন:

উদাহরণস্বরূপ আমার কাছে নিম্নলিখিত স্ট্রিং রয়েছে:

111aabbccxccybbzaa1

আমি দ্বিতীয় ঘটনার পরে সমস্ত সদৃশ অক্ষরগুলি প্রতিস্থাপন করতে চাই। আউটপুটটি হবে:

11-aabbccx--y--z---

আমি এখনও পর্যন্ত চেষ্টা করেছি এমন কিছু রেজেক্স প্যাটার্ন:

নীচের রেজেক্স ব্যবহার করে আমি প্রতিটি চরিত্রের শেষ ঘটনাটি খুঁজে পেতে পারি: (.)(?=.*\1)

বা এটি ব্যবহার করে আমি এটি টানা ডুপ্লিকেটগুলির জন্য করতে পারি তবে কোনও নকলের জন্য নয়: ([a-zA-Z1-9])\1{2,}


1
আপনি কি রেজেক্স ইঞ্জিনটি ব্যবহার করবেন?
উইক্টর স্ট্রিবিউ

1
আপনি কেবলমাত্র এমন একটি রেজেক্সের সাহায্যে এটি করতে পারেন যা অসীম প্রস্থের চেহারাটির পিছনে সমর্থন করে, তাই আপনার একমাত্র বিকল্পটি তখন পাইথন পাইপিআই রেজেক্স মডিউল। এটি (.)(?<=^(?:(?:(?!\1).)*\1){2,}(?:(?!\1).)*\1)রেগেক্স সহ ব্যবহার করুন । ডেমো
উইক্টর স্ট্রিবিউ

3
@ উইক্টরস্ট্রিবিউউউ কি এর চেয়ে ভাল (.)(?<=(.*\1){3})?
স্টিফান পোচম্যান 21

2
@ স্টেফানপোকম্যান ভাল, কাজটিও (.)(?<=(?:.*\1){3})করবেন, তবে এগুলি ভাল নয় কারণ অতিরিক্ত ব্যাকট্র্যাকিংয়ের ফলে দীর্ঘতর স্ট্রিংয়ের সমস্যা হতে পারে। আমি বরং সমস্যাটি সমাধান করার জন্য একটি নন-রেজেক্স পদ্ধতি লিখতাম।
উইক্টর স্ট্রিবিউ

2
@ WiktorStribiżew আমি regexstorm বেশ কয়েকবার মধ্যে teststring, এটি একটি বিশাল স্ট্রিং উপার্জন কপি তবে আমি কর্মক্ষমতা পার্থক্য আপনার প্যাটার্ন 750ms যেমন পেতে (.)(?<=(?:.*\1){3})25ms, (.)(?<=(?:\1.*?){2}\1)3ms। আপনি শুধু নিজেকে পরীক্ষা করতে পারেন। আপনার মনে হয় এটি সবচেয়ে কম দক্ষ প্যাটার্ন এবং এটি পড়া সবচেয়ে কঠিন।
বকবক বুদবুদ

উত্তর:


8

নন-রেজেক্স আর সলিউশন। বিভক্ত স্ট্রিং। এই ভেক্টরের রোুইড> = 3 * থাকার উপাদানগুলি প্রতিস্থাপন করুন '-'। এটি আবার এক সাথে আটকান।

x <- '111aabbccxccybbzaa1'

xsplit <- strsplit(x, '')[[1]]
xsplit[data.table::rowid(xsplit) >= 3] <- '-'
paste(xsplit, collapse = '')

# [1] "11-aabbccx--y--z---"

* rowid(x)হ'ল একটি পূর্ণসংখ্যা ভেক্টর যার সাথে প্রতিটি উপাদানটি সংশ্লিষ্ট উপাদান থেকে প্রাপ্ত মানটির সংখ্যাকে বোঝায় x। সুতরাং যদি শেষ উপাদানটি xহয় 1এবং এটি চতুর্থবারের মতো 1ঘটে থাকে xতবে এর শেষ উপাদানটি rowid(x)হয় 4


4

আপনি সহজেই রেজেক্স ছাড়াই এটি সম্পাদন করতে পারেন:

ব্যবহারের কোডটি এখানে দেখুন

s = '111aabbccxccybbzaa1'

for u in set(s):
    for i in [i for i in range(len(s)) if s[i]==u][2:]:
        s = s[:i]+'-'+s[i+1:]

print(s)

ফলাফল:

11-aabbccx--y--z---

এটি কীভাবে কাজ করে:

  1. for u in set(s) স্ট্রিংটিতে অনন্য অক্ষরের একটি তালিকা পেয়েছে: {'c','a','b','y','1','z','x'}
  2. for i in ... যে সূচকগুলি আমরা 3 এ সংগ্রহ করি তার উপরে লুপ হয়।
  3. [i for i in range(len(s)) if s[i]==u][2:]স্ট্রিংয়ের প্রতিটি চরিত্রের উপরে লুপ করে এবং এটি u(পদক্ষেপ ১ থেকে) মেলে কিনা তা পরীক্ষা করে , তবে এটি ২ য় উপাদান থেকে শেষ পর্যন্ত অ্যারেটি টুকরো টুকরো করে (যদি তারা উপস্থিত থাকে তবে প্রথম দুটি উপাদান বাদ দেয়)
  4. স্ট্রিংটি সেট করুন s[:i]+'-'+s[i+1:]- সূচকটির সাথে স্ট্রিংগুলিকে সূচক দিয়ে -এবং তারপরে সূচকের পরে স্ট্রিংগুলি কার্যকরভাবে মূল চরিত্র বাদ দিয়ে দিন

3

সঙ্গে একটি বিকল্প gsubfn

library(gsubfn)
p <- proto(fun = function(this, x) if (count >=3) '-' else x)
for(i in c(0:9, letters)) x <- gsubfn(i, p, x)
x
#[1] "11-aabbccx--y--z---"

উপাত্ত

x <- '111aabbccxccybbzaa1'

2

পাইপথন ওয়ান-লাইনের কোনও রেজেক্স নেই:

s = "111aabbccxccybbzaa1"

print("".join(char if s.count(char, 0, i) < 2 else "-" for i, char in enumerate(s)))
# ==> "11-aabbccx--y--z---"

এটি স্ট্রিংয়ের মাধ্যমে গণনা করে এটির পিছনে বর্তমান চরিত্রের উপস্থিতি গণনা করা এবং কেবল অক্ষরটিকে প্রথম 2 এর মধ্যে একটিতে রাখলে অন্যথায় ড্যাশ করে।


1

এটি করার আরেকটি উপায় pandas

import pandas as pd

s = '111aabbccxccybbzaa1'
# 11-aabbccx--y--z---

df = pd.DataFrame({'Data': list(s)})
df['Count'] = 1
df['cumsum'] = df[['Data', 'Count']].groupby('Data').cumsum()
df.loc[df['cumsum']>=3, 'Data'] = '-'
''.join(df.Data.to_list())

আউটপুট :

11-aabbccx--y--z---

0

ধন্যবাদ Wiktor Stribiżew , স্টিফান Pochmann এবং bobble বুদ্বুদ । সমাপ্তির স্বার্থে, আমি regexমন্তব্যগুলিতে আলোচিত সম্ভাব্য সমাধানগুলি পোস্ট করছি ;

এটি কেবলমাত্র একটি রেজেক্সের সাথেই করণীয় যা অসীম প্রস্থের চেহারাটির পিছনে সমর্থন করে। পাইথন পাইপিআই রেজেক্স মডিউল ব্যবহার করে আমরা নিম্নলিখিতগুলি করতে পারি:

#python 2.7.12

import regex

s = "111aabbccxccybbzaa1"

print(regex.sub(r'(.)(?<=^(?:(?:(?!\1).)*\1){2,}(?:(?!\1).)*\1)', '-', s)) #Wiktor Stribizew
     ## 11-aabbccx--y--z---

print(regex.sub(r'(.)(?<=(.*\1){3})', '-', s)) #Stefan Pochmann
     ## 11-aabbccx--y--z---

print(regex.sub(r'(.)(?<=(?:.*\1){3})', '-', s)) #Wiktor Stribizew
     ## 11-aabbccx--y--z---

print(regex.sub(r'(.)(?<=(?:\1.*?){2}\1)', '-', s)) #bobble bubble
     ## 11-aabbccx--y--z---

স্নিপেট

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