grep -n | sort | sed | cut
( export LC_ALL=C
grep -n '' | sort -t: -nmk1,1 ./L - |
sed /:/d\;n | cut -sd: -f2-
) <./F
যে কোনও আকারের ইনপুট সহ এটি খুব দ্রুত কাজ করা উচিত (কিছু সময়োচিত পরীক্ষা নীচে অন্তর্ভুক্ত করা হয়েছে) । কীভাবে কিছু নোট:
export LC_ALL=C
- যেহেতু নিম্নলিখিত ক্রিয়াকলাপের বিষয়টি হ'ল লিনেনোর ফাইলের
./F
সাথে ./L
সজ্জিত পুরো ফাইলটি ইনলাইন করা , কেবলমাত্র যে অক্ষরগুলির জন্য আমাদের চিন্তার দরকার তা হ'ল ASCII [0-9]
সংখ্যা এবং :
কোলন।
- সেই কারণে যদি ইউটিএফ -8 অন্যথায় জড়িত থাকে তবে তার চেয়ে 128 সম্ভাব্যতার একটি সেটে এই 11 টি অক্ষর খুঁজে পাওয়ার বিষয়ে চিন্তা করা আরও সহজ।
grep -n ''
- এটি স্টিডিনের
LINENO:
প্রতিটি লাইনের মাথায় স্ট্রিংটি সন্নিবেশ করায় - বা <./F
।
sort -t: -nmk1,1 ./L -
sort
এটির ইনপুট ফাইলগুলি একেবারে বাছাই করতে অবহেলা করে এবং পরিবর্তে (সঠিকভাবে) অনুমান করা হয় যে তারা প্রেরিত রয়েছে এবং -m
তাদের -numerically
সাজানো ক্রমে উত্সাহ দেয় , যাইহোক যে কোনও সম্ভাব্য স্ট্রেন -k1,1
সংঘটিত -t:
কোলন চরিত্রের বাইরে মূলত কিছু উপেক্ষা করে ।
- যদিও এটি করার জন্য কিছু অস্থায়ী জায়গার প্রয়োজন হতে পারে (কিছু সিকোয়েন্সগুলি কতটা পৃথক হতে পারে তার উপর নির্ভর করে) , এটি সঠিক ক্রমের তুলনায় খুব বেশি প্রয়োজন হবে না এবং এটি খুব দ্রুত হবে কারণ এতে শূন্য ব্যাকট্র্যাকিং জড়িত।
sort
একটি একক স্ট্রিম আউটপুট দেবে যেখানে কোনও লিনেনস ./L
তত্ক্ষণাত এর সাথে সম্পর্কিত লাইনগুলির আগে চলে যাবে ./F
। ./L
এর লাইনগুলি সর্বদা প্রথমে আসে কারণ সেগুলি সংক্ষিপ্ত।
sed /:/d\;n
- যদি বর্তমান লাইনটি কোনও
/:/
কোলনের সাথে d
আউটপুট থেকে একাদশ করে। অন্যথায়, বর্তমান এবং n
এক্সট লাইনটি স্বয়ংক্রিয়ভাবে মুদ্রণ করুন ।
- এবং সুতরাং
sed
prunes sort
এর আউটপুটটি কেবল ক্রমযুক্ত লাইন জোড়া যা কোনও কোলন এবং নিম্নলিখিত লাইনের সাথে মেলে না - বা, কেবল একটি লাইন থেকে ./L
এবং তারপরে পরের।
cut -sd: -f2-
cut
-s
আউটপুট থেকে বড়গুলি এর ইনপুট লাইনগুলিতে অন্তত একটির -d:
এলিমিটার স্ট্রিং ধারণ করে না - এবং ./L
এর লাইনগুলি সম্পূর্ণ ছাঁটাই হয়।
- যে লাইনগুলি করে তাদের জন্য, তাদের প্রথম
:
কোলন-সীমাবদ্ধ -f
আইল্ডটি cut
দূরে রয়েছে - এবং তাই সমস্ত grep
linোকানো লিনেনোর।
ছোট ইনপুট পরীক্ষা
seq 5 | sed -ne'2,3!w /tmp/L
s/.*/a-z &\& 0-9/p' >/tmp/F
... নমুনা ইনপুট 5 লাইন উত্পাদন করে। তারপর ...
( export LC_ALL=C; </tmp/F \
grep -n '' | sort -t: -nmk1,1 ./L - |
sed /:/d\;n | cut -sd: -f2-
)| head - /tmp[FL]
... কপি করে প্রিন্ট ...
==> standard input <==
a-z 1& 0-9
a-z 4& 0-9
a-z 5& 0-9
==> /tmp/F <==
a-z 1& 0-9
a-z 2& 0-9
a-z 3& 0-9
a-z 4& 0-9
a-z 5& 0-9
==> /tmp/L <==
1
4
5
বড় সময়সীমা পরীক্ষা
আমি বেশ কয়েকটি বড় ফাইল তৈরি করেছি:
seq 5000000 | tee /tmp/F |
sort -R | head -n1500000 |
sort -n >/tmp/L
... যা এতে 5 /tmp/F
মিলিল লাইন এবং এর মধ্যে 1.5mil এলোমেলোভাবে নির্বাচিত লাইন স্থাপন করে /tmp/L
। আমি তখন করেছি:
time \
( export LC_ALL=C
grep -n '' | sort -t: -nmk1,1 ./L - |
sed /:/d\;n | cut -sd: -f2-
) <./F |wc - l
এটি মুদ্রিত:
1500000
grep -n '' \
0.82s user 0.05s system 73% cpu 1.185 total
sort -t: -nmk1,1 /tmp/L - \
0.92s user 0.11s system 86% cpu 1.185 total
sed /:/d\;n \
1.02s user 0.14s system 98% cpu 1.185 total
cut -sd: -f2- \
0.79s user 0.17s system 80% cpu 1.184 total
wc -l \
0.05s user 0.07s system 10% cpu 1.183 total
(আমি সেখানে ব্যাকস্ল্যাশ যুক্ত করেছি)
বর্তমানে এখানে প্রদত্ত সমাধানগুলির মধ্যে, এটি আমার মেশিনে উপরে উত্পন্ন ডেটাসেটের বিরুদ্ধে যখন খড়খড়ি করে তবে এটি সবার দ্রুততম। অন্যদের মধ্যে কেবল একজনই দ্বিতীয় স্থান অর্জনের পক্ষে লড়াইয়ের কাছাকাছি এসেছিল, এবং তা হ'ল perl
এখানে মেহ ।
এটি কোনওভাবেই দেওয়া আসল সমাধানটি নয় - এটি অন্যের দেওয়া পরামর্শ / অনুপ্রেরণার জন্য তার কার্যকর সময়টির এক তৃতীয়াংশ বাদ পড়েছে। ধীর সমাধানের জন্য পোস্টের ইতিহাস দেখুন (তবে কেন?) ।
এছাড়াও, এটি লক্ষণীয় যে এটি যদি আমার সিস্টেমের মাল্টি-সিপিইউ আর্কিটেকচার এবং সেই পাইপলাইনের প্রতিটি প্রক্রিয়াটির একযোগে সম্পাদনের জন্য না হয় তবে অন্য কিছু উত্তর খুব ভালভাবে লড়াই করতে পারে। এগুলি সমস্ত একই সময়ে কাজ করে - প্রত্যেকে তার নিজস্ব প্রসেসরের মূল অংশে - ডেটা ঘুরে এবং পুরো অংশে তাদের ছোট অংশটি করে। বেশ সুন্দর।
তবে দ্রুততম সমাধানটি হ'ল ...
তবে এটি দ্রুততম সমাধান নয়। এখানে দেওয়া দ্রুততম সমাধানটি হ্যান্ড-ডাউন, সি প্রোগ্রাম । আমি বলেছি cselect
। এটি আমার এক্স ক্লিপবোর্ডে অনুলিপি করার পরে, আমি এটি এর মতো সংকলন করেছি:
xsel -bo | cc -xc - -o cselect
আমি তখন করেছি:
time \
./cselect /tmp/L /tmp/F |
wc -l
... এবং ফলাফলগুলি ছিল ...
1500000
./cselect /tmp/L /tmp/F \
0.50s user 0.05s system 99% cpu 0.551 total
wc -l \
0.05s user 0.05s system 19% cpu 0.551 total