बाइनरी नंबर के अनुसार शब्दों की सूची बनाएं


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
@ fusion.slope, या तो पूरे कोड के लिए एक एकल उद्धृत तर्क में पारित 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 ई 1 एफ 0 जी 0 एच 0 मैं 1 मिलता है
  • ${(j<>)...} तत्वों के साथ जुड़ता है, इस बीच कुछ भी नहीं होता है इसलिए यह A0B0C0D0E1F0G0H0I1 हो जाता है
  • ${...//(?0|1)}हम पट्टी करते हैं ?0और 1उसमें से यह ईआई बन जाता है:
  • ${(s<>)...} प्रति अक्षर एक तत्व की एक सरणी प्राप्त करने के लिए कुछ नहीं पर विभाजित: ईआई
  • ${(j<,>)...}उन लोगों के साथ जुड़ें ,-> ई, आई।

यह सिर्फ एक साधारण बैश सही है?
संलयन।

1
@ fusion.slope, नहीं, वह zsh, एक अलग शेल bash(और बहुत अधिक शक्तिशाली है, और यदि आप पूछें तो बेहतर डिज़ाइन के साथ)। bashकेवल एक छोटे से अंश उधार लिया है zshकी सुविधा (जैसे {1..4}, <<<, **/*) नहीं लोगों को यहाँ उल्लेख किया है, में से अधिकांश bashकी सुविधाओं अन्यथा से उधार लिया जाता है ksh
स्टीफन चेज़लस

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/,$//'

GNU के साथ 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'

ऊपर के रूप में एक ही है जब हम कुछ अनुकूलन के लिए अनुमति देता है जो अनुवादित और सूचकांक भागों गमागमन कर रहे हैं।


यदि आप समझा सकते हैं तो समुदाय के लिए अच्छा होगा। अग्रिम धन्यवाद
fusion.slope

1
@ fusion.slope, संपादन देखें।
स्टीफन चेज़लस

t1 कमांड के साथ लूप अच्छा है!
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
कृपया बताएं कि यह क्या करता है और यह कैसे काम करता है।
स्कॉट

कृपया भाषा भी।
संलयन .slope
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.