বাইনারি সংখ্যা অনুসারে শব্দগুলির তালিকা তৈরি করুন


12

আমার একটি ম্যাট্রিক্স রয়েছে যা দেখতে নীচের মত দেখাচ্ছে:

ইনপুট :

A   B   C   D   E   F   G   H   I 
0   0   0   0   1   0   0   0   1
0   0   0   1   0   0   0   0   0  
0   0   0   1   0   0   0   0   0  
1   0   0   0   0   0   0   0   0  
1   0   1   0   0   0   1   0   0  
1   0   0   1   0   0   0   1   0  
1   0   0   0   1   1   1   0   0  

এবং আমি প্রতিটি সারির জন্য মান 1 এর সাথে সম্পর্কিত চিঠির তালিকাটি বের করতে চাই।

আউটপুট :

E,I 
D
D
A
A,C,G  
A,D,H  
A,E,F,G  

আমি শিরোনামকে বিভক্ত করার এবং শব্দগুলির সাথে সংখ্যার সাথে মিল রাখার চেষ্টা করেছি কিন্তু আমি ব্যর্থ হয়েছি।

উত্তর:


12

ইন awk:

NR == 1 { for(column=1; column <= NF; column++) values[column]=$column; }
NR > 1 { output=""
        for(column=1; column <= NF; column++)
                if($column) output=output ? output "," values[column] : values[column]
        print output }

6
এছাড়াও ব্যবহার করতে পারেনNR == 1 { split($0,values) }
সন্দীপ

এটি দ্বিতীয় লাইন এড়িয়ে চলেছে। nextপ্রথম লাইনের শেষে একটি রাখার বিষয়টি বিবেচনা করুন যাতে আপনার পরবর্তী লাইনের জন্য বিপরীত অবস্থার পরীক্ষা করতে হবে না।
এড মর্টন

1
আসল ইনপুট পাঠ্যের এটিতে একটি অতিরিক্ত ফাঁকা রেখা উপস্থিত ছিল যা আমি কোড করে রেখেছিলাম। এটি এডিট করা হয়েছে, সুতরাং কেবল পরিবর্তন NR > 2করুন NR > 1
জেফ শ্যাচলার

1
"গল্ফিং" টিপের জন্য আপনাকে ধন্যবাদ, সন্দীপ! আমি মনে করি যে আমি স্পষ্টতাকে 'লুপের জন্য পছন্দ করি কারণ এটি দেহের' ফর 'লুপের সাথে দৃষ্টিভঙ্গি / যৌক্তিকভাবে লাইন করে যায়।
জেফ শ্যাচলার

1
@ ফিউশন.স্লোপ, হয় সম্পূর্ণ কোডটি একটি একক-উদ্ধৃত যুক্তি দিয়ে পাস করুন awk, অথবা কোডটি একটি ফাইলের মধ্যে পেস্ট করুন এবং এটি দিয়ে চালানawk -f that.script.file input-file
জেফ শ্যাচলার

6

সঙ্গে অন্য এক perl

$ perl -lane 'if($. == 1){ @h=@F }
              else{@i = grep {$F[$_]==1} (0..$#F); print join ",",@h[@i]}
             ' ip.txt
E,I
D
D
A
A,C,G
A,D,H
A,E,F,G
  • -a@Fঅ্যারেতে উপলভ্য, সাদা-স্পেসে ইনপুট লাইন বিভক্ত করার বিকল্প
  • if($. == 1){ @h=@F } প্রথম লাইনে শিরোনাম সংরক্ষণ করুন
  • @i = grep {$F[$_]==1} (0..$#F) প্রবেশের তালিকা থাকলে সংরক্ষণ করুন 1
  • print join ",",@h[@i],বিভাজক হিসাবে ব্যবহার করে কেবল শিরোনাম অ্যারে থেকে সূচকগুলি মুদ্রণ করুন

4

এখনও এটি মজাদার জন্য, একটি zshসংস্করণ:

{
   read -A a  &&
   while read -A b; do
     echo ${(j<,>)${(s<>)${(j<>)a:^b}//(?0|1)}}
   done
} < file
  • ${a:^b} দুটি অ্যারে জিপ করুন, যাতে আপনি একটি 0 বি 0 সি 0 ডি 0 ই 0 এফ 0 জি 0 এইচ 0 আই 1 পান
  • ${(j<>)...} এর মধ্যে কিছুই না দিয়ে উপাদানগুলিতে যোগ দেয় তাই এটি A0B0C0D0E1F0G0H0I1 হয়ে যায়
  • ${...//(?0|1)}আমরা এটিটি ছাঁটাই ?0এবং 1এটি থেকে এটি EI হয়ে যায়:
  • ${(s<>)...} চিঠি অনুসারে একটি উপাদানের অ্যারে পেতে কিছুইতে বিভক্ত করুন: EI
  • ${(j<,>)...},-> ই, আই সহ যাদের সাথে যোগ দিন ।

এই ঠিক একটি সহজ বাশ অধিকার?
fusion.slope

1
@ ফিউশন.স্লোপ, না, এটির zshথেকে আলাদা শেল bash(এবং আরও শক্তিশালী এবং আপনি যদি আমাকে জিজ্ঞাসা করেন তবে আরও ভাল নকশা সহ) এখানে বর্ণিত বৈশিষ্ট্যগুলি নয় , bashকেবলমাত্র zshএর বৈশিষ্ট্যটির (যেমন , ) একটি ক্ষুদ্র ক্ষুদ্র অংশ ধার নিয়েছে , বেশিরভাগ বৈশিষ্ট্যই অন্যথায় ধার করা হয়েছে । {1..4}<<<**/*bashksh
স্টাফেন চ্যাজেলাস

3

আর একটি বিশ্রী সমাধান:

awk 'NR==1{ split($0,a); next }   # capture and print `header` fields
     { for (i=1;i<=NF;i++)         # iterating through value fields `[0 1 ...]`
           if ($i) { printf "%s",(f?","a[i]:a[i]); f=1 } 
       f=0; print "" 
     }' file

আউটপুট:

E,I
D
D
A
A,C,G
A,D,H
A,E,F,G

2

এখানে পার্লের একটি সমাধান দেওয়া হয়েছে:

use strict;

my @header = split /\s+/, <>;
<>; ## Skip blank line
while (<>) {
    my @flags = split /\s+/;
    my @letters = ();
    for my $i (0 .. scalar @flags - 1) {
        push @letters, $header[$i] if $flags[$i];
    }

    print join(',', @letters), "\n";
}

এটি শিরোনামে শিরোনাম কলামগুলি পাঠ করে এবং তারপরে, প্রতিটি ডেটা সারির জন্য, মিলিয়ে ডেটা কলামটি সত্য হিসাবে মূল্যায়ন করলে কলামের নাম আউটপুট অ্যারে অনুলিপি করে। কলামের নামগুলি পরে কমা-বিচ্ছিন্ন মুদ্রিত হয়।


2

sedএটি মজাদার জন্য একটি :

sed '
  s/ //g
  1{h;d;}
  G;s/^/\
/
  :1
    s/\n0\(.*\n\)./\
\1/
    s/\n1\(.*\n\)\(.\)/\2\
\1/
  t1
  s/\n.*//
  s/./&,/g;s/,$//'

জিএনইউ দিয়ে sedআপনি এটিকে কিছুটা স্পষ্ট করে তুলতে পারেন:

sed -E '
  s/ //g # strip the spaces

  1{h;d} # hold the first line

  G;s/^/\n/ # append the held line and prepend an empty line so the
            # pattern space becomes <NL>010101010<NL>ABCDEFGHI we will
            # build the translated version in the part before the first NL
            # eating one character at a time off the start of the
            # 010101010 and ABCDEFGHI parts in a loop:
  :1
    s/\n0(.*\n)./\n\1/     # ...<NL>0...<NL>CDEFGHI becomes
                           # ...<NL>...<NL>DEFGHI (0 gone along with C)

    s/\n1(.*\n)(.)/\2\n\1/ # ...<NL>1...<NL>CDEFGHI becomes
                           # ...C<NL>...<NL>DEFGHI (1 gone but C moved to 
                           #                        the translated part)
  t1 # loop as long as any of those s commands succeed

  s/\n.*// # in the end we have "ADG<NL><NL>", strip those NLs

  s/./,&/2g # insert a , before the 2nd and following characters'

একটি সামান্য সংক্ষিপ্ত সংস্করণ, ধরে নেওয়া এই যে প্রতিটি লাইনে সর্বদা একই সংখ্যার সংখ্যা থাকে:

sed -E '
  s/ //g
  1{H;d}
  G
  :1
    s/^0(.*\n)./\1/
    s/^1(.*\n)(.*\n)(.)/\1\3\2/
  t1
  s/\n//g
  s/./,&/2g'

উপরের মত একই আমরা অনুবাদ করা এবং সূচক অংশগুলি অদলবদল করছি যা কিছু অপ্টিমাইজেশনের জন্য অনুমতি দেয় except


আপনি যদি ব্যাখ্যা করতে পারেন তবে সম্প্রদায়ের পক্ষে ভাল হবে। অগ্রিম ধন্যবাদ
fusion.slope

1
@ ফিউশন.স্লোপ, সম্পাদনা দেখুন।
স্টাফেন চেজেলাস

টি 1 কমান্ড সহ লুপটি চমৎকার!
fusion.slope

1

python3

python3 -c '
import sys
header = next(sys.stdin).rstrip().split()
for line in sys.stdin:
  print(*(h*int(f) for (h, f) in zip(header, line.rstrip().split()) if int(f)), sep=",")

  ' <file
E,I
D
D
A
A,C,G
A,D,H
A,E,F,G

0

খাঁটি বাশ সমাধান:

read -a h
while read -a r
do (
    for i in ${!r[@]}
    do 
        (( r[i] == 1 )) && y[i]=${h[i]}
    done
    IFS=,
    echo "${y[*]}")
done

3
এটি কীভাবে সমস্যার সমাধান করে তা ব্যাখ্যা করুন।
স্কট

পাঠকের জন্য অনুশীলন হিসাবে এটি বাকি রয়েছে। বেসিক বাশ জ্ঞান ধরে নেওয়া LESS="+/^ {3}Array" man bashবাশ অ্যারেগুলির জন্য প্রয়োজনীয় সমস্ত তথ্য দেওয়া উচিত। যে কোনও সহায়ক স্পষ্টতা যোগ করতে আপনি উত্তর সম্পাদনা করতে নির্দ্বিধায়।
ডেভিড ওঙ্গারো

-1
 void Main(string[] args)
        {
            int[,] numbers = new int[,]
            {
            {0, 0, 0, 0, 1, 0, 0, 0, 1},
            {0, 0, 0, 1, 0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0, 0, 0, 0, 0},
            {1, 0, 0, 0, 0, 0, 0, 0, 0},
            {1, 0, 1, 0, 0, 0, 1, 0, 0},
            {1, 0, 0, 1, 0, 0, 0, 1, 0},
            {1, 0, 0, 0, 1, 1, 1, 0, 0}
            };
            string letters = "ABCDEFGHI";
            for (int row = 0; row < 7; row++)
            {
                for (int col = 0; col < 9; col++)
                {
                    if (numbers[row, col] == 1)
                        Console.Write(letters[col]);
                }
                Console.WriteLine();
            }
        }

3
এটি কী করে এবং এটি কীভাবে কাজ করে তা দয়া করে ব্যাখ্যা করুন।
স্কট

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