ফাইল এ এর ​​সমস্ত লাইন সরান যা ফাইল বি তে স্ট্রিং রয়েছে


15

ব্যবহারকারীর নাম users.csv, ইউজারআইডি এবং অন্যান্য ডেটার তালিকা সহ আমার কাছে সিএসভি ফাইল রয়েছে:

username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"Paul McCartny", 30923833, "left", "black"
"Ringo Starr", 77392318, "right", "blue"
"George Harrison", 72349482, "left", "green"

অন্য একটি ফাইলে toremove.txtআমার কাছে ইউজারআইডিদের একটি তালিকা রয়েছে:

30923833
77392318

users.csvআইডি থাকা ফাইল থেকে সমস্ত সারি অপসারণ করার জন্য কি কোনও চতুর, দক্ষ উপায় আছে toremove.txt? আমি দুটি ফাইল পার্স করার জন্য একটি পাইথন অ্যাপ লিখেছি এবং একটি নতুন ফাইলে লিখতে কেবল সেই লাইনগুলিতে পাওয়া যায় নি toremove.txt, তবে এটি অসাধারণ ধীর। সম্ভবত কিছু sedবা awkযাদু এখানে সাহায্য করতে পারেন?

উপরের উদাহরণগুলি বিবেচনা করে এটি কাঙ্ক্ষিত ফলাফল:

username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"

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

স্ক্রিপ্টটি আসলে ও (এন <<< 2 </sup>): n users.csvফাইলের লাইনের জন্য, এবং এর লাইনের জন্য n toremove.txt। কম জটিলতায় কীভাবে এটি করা যায় আমি সত্যিই নিশ্চিত নই। এটি সারকথা হল: for u in users: if not any(toremove in u): outputfile.write(u)। আমি কোড পর্যালোচনা পোস্ট করতে পারেন।
dotancohen

1
আমি পড়তাম toremove.txt, কীগুলি হিসাবে এন্ট্রিগুলি সংরক্ষণ করতাম । ইউজার সিএসভি আইট্রেট করুন, আইডি ডিকটিতে নেই এমনগুলি মুদ্রণ করুন। আপনি উভয় জন্য পেতে হে (ঢ) প্রক্রিয়াকরণের toremove.txtএবং users.csv, এবং হে (ঢ) মেমোরি ব্যবহার toremove.txt(যা সম্ভবত অপেক্ষাকৃত ছোট হয়)
এঞ্জেল

@ আঞ্জেল: হ্যাঁ, স্ক্রিপ্টটি ঠিক এভাবে কাজ করে!
dotancohen

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

উত্তর:


15

সহ grep, আপনি এটি করতে পারেন:

$ grep -vwF -f toremove.txt users.txt 
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"

সহ awk:

$ awk -F'[ ,]' 'FNR==NR{a[$1];next} !($4 in a)' toremove.txt users.txt 
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"

@ আটারডন: ডাং! আমি এটা বলতে যাচ্ছিলাম। দ্রষ্টব্য, যদিও, যে জ্নুকের উত্তর (তর্কযুক্ত) প্রশ্নটি যা জিজ্ঞাসা করে তা করে , তবে এটি ব্যবহারকারী যা চায় তা নাও হতে পারে।
স্কট

awkসমাধান অত্যন্ত ফাইল 'ফরম্যাট হচ্ছে সংবেদনশীল ঠিক যেমন প্রশ্নে দেখানো হয়েছে। অত্যন্ত সুস্পষ্টরূপে, যদি কোনও নামটি কেবল একটি শব্দ / টোকেন হয় (যেমন, এতে কোনও স্পেস নেই; যেমন, "Bono") বা দুটি টোকেনের বেশি (যেমন, এটিতে একাধিক স্পেস থাকে; যেমন, "Sir Paul McCartney") এটি প্রবেশ করবে এমনকি যদি ব্যবহারকারীর মিল। কম স্পষ্টতই, প্রথম কমা এবং ইউজারিডের মধ্যে কোনও স্থান না থাকলে বা একাধিক স্পেস (যেমন, "John Lennon", 90123412, …) না থাকলে একই জিনিস ঘটে ।
স্কট

@ স্কট: হ্যাঁ, এ কারণেই আমি awkসমাধানটি পিছনে grep
ফেলেছি

4

মহাকাশের awkউত্তর, স্থান-অন্ধ হিসাবে সংশোধিত এখানে :

awk -F, 'FNR==NR{a[$1];next} !(gensub("^ *","",1,$2) in a)' toremove.txt users.csv

এটা বিভেদক রূপে শুধুমাত্র কমা (এবং স্পেস) ব্যবহার থেকে, $1হয় "John Lennon", $2হয়  90123412, ইত্যাদি সুতরাং আমরা ব্যবহার করুন (একটি নেতৃস্থানীয় স্থান সহ) gensubথেকে নেতৃস্থানীয় স্পেস যে কোন সংখ্যার মুছে ফেলার জন্য $2 আগে আমরা পরীক্ষা কিনা এটা (আইডি) ছিলেন toremove.txtফাইল।


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

আমি বিশ্বাস করি আমি যা করছি তোমার মনে কি ছিল?
স্কট

হ্যা, তুমি. আমি শুধু যদি আপনি কিছু একটি লাইন বা যে (downcasing, ইত্যাদি ভালো কিছু প্রথমার্ধে সরানোর মত আরো ভীতু না করা প্রয়োজন উল্লেখ ছিল stackoverflow.com/a/4784647/32453 ) শুধু বিশেষ পার্সিং
rogerdpack

0

রুবি উপায় ঠিক আছে: যদি আপনার কোনও ফাইলের স্ট্রিংগুলির একটি তালিকা থাকে এবং আপনি অন্য ফাইল থেকে সমস্ত লাইন মুছে ফেলতে চান যা এমনকি প্রথম ফাইলে কোনও স্ট্রিং রয়েছে (এই ক্ষেত্রে "ফাইল 1" "ফাইল 1" থেকে অপসারণ) রুবি ফাইল :

b=File.read("file2").split # subtract this one out
remove_regex = Regexp.new(b.join('|'))
File.open("file1", "r").each_line do |line|
  if line !~ remove_regex
    puts line
  end
end

দুর্ভাগ্যক্রমে একটি বৃহত "মুছে ফেলা" ফাইলের সাথে এটি জটিলতার ভিত্তিতে হে (এন ^ 2) হ্রাস পাবে বলে মনে হচ্ছে (আমার ধারনাটি হ'ল রেজিপ্লেক্সের অনেক কাজ আছে) তবে এখনও কারও পক্ষে এটি কার্যকর হতে পারে (আপনি যদি হন) সম্পূর্ণ লাইন সরানোর চেয়ে আরও বেশি কিছু চান)। এটি কিছু ক্ষেত্রে দ্রুত হতে পারে।

আপনি যদি গতিতে যাচ্ছেন তবে অন্য একটি বিকল্প হ'ল একই হ্যাশ চেকিং মেকানিজম ব্যবহার করা, তবে সাবধানে মেলে এমন স্ট্রিংগুলির জন্য লাইনটি সাবধানে "পার্স" করা, তারপরে তাদের আপনার হ্যাশের সাথে তুলনা করে।

রুবিতে, এ জাতীয় চেহারা হতে পারে:

b=File.read("file2").split # subtract this one out
hash={}
for line in b
  hash[line] = 1
end

ARGF.each_line do |line|
  ok = true
  for number in line.scan(/\d{9}/)
    if hash.key? number
      ok=false
    end
  end
  if (ok)
    puts line
  end
end

স্কটের উত্তরও দেখুন, এটি এখানে প্রস্তাবিত বিশৃঙ্খল উত্তরের সাথে সমান এবং ও (এন ^ 2) জটিলতা (ভাও) এড়িয়ে চলে।

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