同じ最初のフィールドを持つ行をマージするためのOneliner


15

これは私の最初のcodegolfの質問なので、適切でない場合は事前に謝罪し、フィードバックを歓迎します。

次の形式のファイルがあります。

a | rest of first line
b | rest of second line
b | rest of third line
c | rest of fourth line
d | rest of fifth line
d | rest of sixth line

実際の内容は、区切り文字と同様に異なります。内容は単なるテキストです。区切り文字は1行に1回だけ表示されます。このパズルでは、区切り文字を自由に変更してください。たとえば、「%」を区切り文字として使用します。

望ましい出力:

a | rest of first line
b | rest of second line % rest of third line
c | rest of fourth line
d | rest of fifth line % rest of sixth line

私はすでにこれをマージするためにrubyとawkの両方のスクリプトを持っていますが、短いonelinerを持つことは可能だと思います。すなわち、コマンドラインでパイプや他のコマンドと一緒に使用できるワンライナー。私はそれを理解することはできません、そして私自身のスクリプトはコマンドラインでただ圧縮したいです。

最短文字が優先されます。入力は必ずしもソートされるわけではありませんが、連続する行を一致する最初のフィールドにマージすることだけに関心があります。最初のフィールドに一致する無制限の行があります。フィールド1は、果物の名前、固有名詞など、何でもかまいません。

(私はMacOS上で動作するので、個人的にはMac上で動作する実装に最も興味があります)。


次に、2番目の例/テストを示します。「|」に注意してください 区切り文字です。「|」の前のスペース 無関係であり、再送をキーの一部と見なす必要がある場合。出力で区切り文字として「%」を使用していますが、区切り文字を自由に変更できます(ただし、角かっこは使用しないでください)。

入力:

why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination
whom|[possessive] whose
whom|[subjective] who
whoever|[objective] whomever
whoever|[possessive] whosever
who|[possessive] whose
who|[objective] whom

望ましい出力:

why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
whoever|[objective] whomever%[possessive] whosever
who|[possessive] whose%[objective] whom

出力の先頭に改行を使用できますか?
ミリバイト

元の質問にコメントを追加しました。そして、@ mIllIbyte、改行は私とは無関係です。しかし、私の考えでは、空白行やエラーチェックはありません。すべての行にテキストがあり、少なくとも最初の列と区切り文字があると仮定します。
MichaelCodes

テストケースから判断すると、すべてのキーがグループ化されていると仮定しても問題ありませんか?すなわち:["A|some text", "B|other text", "A|yet some other text"]のキーワードので、試験に所望の入力ではありませんAリストで次々ません。
ケビンCruijssen 16年

すべてのキーがグループ化されていると仮定しました。理論的には一意のキーのように扱われることはありませんが、それらがそうでない場合は関係ありません。
MichaelCodes

回答:


7

網膜、17バイト

  • @MartinEnderのおかげで12バイト節約
  • @ jimmy23013のおかげで1バイト節約

ISO 8859-1エンコードバイトでスコア付けされます。

入力フィールドの区切り文字としての;代わりに使用し|ます。

(?<=(.+;).+)¶\1
%

オンラインでお試しください。



2
@LeakyNunルックアラウンドはアトミックであるため。ルックアラウンドが最初に使用されるとき、それは行のプレフィックス全体をキャプチャし、その後、正規表現エンジンはその中にバックトラックしません。
マーティンエンダー

5

V 16 13バイト

òí^¨á«©.*úsî±

オンラインでお試しください!

あなたが言った

区切り文字を自由に変更してください

だから私は選んだ |、区切り文字としてました。これが無効な場合はお知らせください。変更します。

説明:

ò                #Recursively:
 í               #Search for the following on any line:
  ^¨á«©          #1 or more alphabetic characters at the beginning of the line
       .*        #Followed by anything
         ús      #Mark everything after this to be removed:
           î±    #A new line, then the first match again (one or more alphabetic characters)

1
あなたに知らせる???
エリックアウトゴルファー16年

@ΈρικΚωνσταντόπουλοςはい?問題ありますか?
DJMcMayhem

このパズルでは、区切り文字を自由に変更してください。たとえば、「%」を区切り文字として使用します。ないすなわち
エリックアウトゴルファー

2
「|」区切り文字は問題ありません。
MichaelCodes

@MichaelCodesソリューションが重要かどうかを確認できるように、さらにテストケースを追加してください。
DJMcMayhem

3

Perl -0n、2 + 43 = 45バイト

s/
.*\|/%/g,print for/(.*\|)((?:
\1|.)*
)/g

デモ:

$ perl -0ne 's/
> .*\|/%/g,print for/(.*\|)((?:
> \1|.)*
> )/g' <<EOF
> why|[may express] surprise, reluctance, impatience, annoyance, indignation
> whom|[used in] questions, subordination
> whom|[possessive] whose
> whom|[subjective] who
> whoever|[objective] whomever
> whoever|[possessive] whosever
> who|[possessive] whose
> who|[objective] whom
> EOF
why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
whoever|[objective] whomever%[possessive] whosever
who|[possessive] whose%[objective] whom

3

SQL(PostgreSQL)、43 72バイト

COPY T FROM'T'(DELIMITER'|');SELECT a,string_agg(b,'%')FROM T GROUP BY A

これは、PostgreSQLの便利なstring_agg集約関数を利用します。入力は、T2つの列Aとで呼び出されるテーブルからBです。質問にうまく対応するために、ファイルからテーブルにデータをロードするコマンドを追加しました。ファイルはTも同様です。テーブル作成ステートメントをカウントしていません。
出力は順不同になりますが、それが問題である場合、それを修正することができますORDER BY A

SQLFiddleは私のためにプレイしたくありませんでしたが、これはセットアップで得られるものです。

CREATE TABLE T (A VARCHAR(9),B VARCHAR(30));

COPY T FROM'T'(DELIMITER'|');SELECT a,string_agg(b,'%')FROM T GROUP BY A
a   string_agg
--- ----------------------------------------
c   rest of fourth line
b   rest of second line%rest of third line
a   rest of first line
d   rest of fifth line%rest of sixth line

1
公平を期すために、表に指定されたファイル形式の内容を読み取るCOPYコマンドを含めることをお勧めします。そうしないと、他の人と同じ問題を解決できません。
ジュール

@Jules まあ、私が答えたとき、このデフォルトのI / Oコンセンサスを考えていました。答えを編集しますが、質問を読み直します。
MickyT

2

C、127バイト

o[99],n[99],p=n;main(i){for(;gets(n);strncmp(o,n,i-p)?printf(*o?"\n%s":"%s",n),strcpy(o,n):printf(" /%s",i))i=1+strchr(n,'|');}

gccで動作します。区切り文字をに変更しました/。stdinから入力を受け取り、出力をstdoutに書き込むため、入力リダイレクトで呼び出します./a.out <filename

ゴルフをしていない:

o[99],n[99] //declare int, to save two bytes for the bounds
,p=n; //p is an int, saves one byte as opposed to applying an (int) cast to n,
//or to declaring o and n as char arrays
main(i){for(;gets(n);strncmp(o,n,i-p //an (int)n cast would be needed;
// -(n-i) does not work either,
//because pointer arithmetics scales to (int*)
)?printf(*o?"\n%s":"%s" //to avoid a newline at the beginning of output
,n),strcpy(o,n):printf(" /%s",i))i=1+strchr(n,'|');}


1

Python 3-146バイト

入力はファイルのファイル名またはファイルパス、出力はstdoutです。コマンドラインから生のテキストとして入力を取得できれば、はるかに短くなる可能性があります

stdinから入力を受け取り、stdinに出力します。separatorを使用し"|"たセットアップ。最初の入力例をテストするには、区切り記号を使用します" | "

from itertools import*
for c,b in groupby([x.split("|")for x in input().split("\n")],key=lambda x:x[0]):print(c,"|"," % ".join((a[1]for a in b)))

このチャレンジでは、入力をファイルから明示的に読み取る必要はないため、デフォルトのI / Oメソッドがここに適用されると思います。また、他の回答もSTDINからの入力を受け取るため、OPはそれで問題ないと思います。
デンカー

@DenkerAffeよし、編集します。stdinから実際の複数行の入力を行うこともできないと思うので、まったく使い物になりません。
キーティンゲ

ただし、スクリプトを実行すると、入力のリダイレクトを行うことができます。
ミリバイト

1

Java 7、167バイト

別のアプローチを使用することで、おそらくもっとゴルフをすることができます。

import java.util.*;Map c(String[]a){Map m=new HashMap();for(String s:a){String[]x=s.split("=");Object l;m.put(x[0],(l=m.get(x[0]))!=null?l+"%"+x[1]:x[1]);}return m;}

注:上記のメソッドHashMapは、目的のキーと値のペアを作成して返します。ただし、|キーと新しい値の間の出力区切り文字としてOPの質問のように、正確な出力で出力しません。審査MickeyTのSQL回答彼がデータベーステーブルを返したこれは許可されていると考えました。印刷機能のためにこれ以上のバイトを追加する必要がない場合。

未ゴルフ&テストコード:

import java.util.*;

class Main{

    static Map c(String[] a){
        Map m = new HashMap();
        for(String s : a){
            String[] x = s.split("\\|");
            Object l;
            m.put(x[0], (l = m.get(x[0])) != null
                            ? l + "%" + x[1]
                            : x[1]);
        }
        return m;
    }

    public static void main(String[] a){
        Map m = c(new String[]{
            "why|[may express] surprise, reluctance, impatience, annoyance, indignation",
            "whom|[used in] questions, subordination",
            "whom|[possessive] whose",
            "whom|[subjective] who",
            "whoever|[objective] whomever",
            "whoever|[possessive] whosever",
            "who|[possessive] whose",
            "who|[objective] whom"
        });

        // Object instead of Map.EntrySet because the method returns a generic Map
        for (Object e : m.entrySet()){
            System.out.println(e.toString().replace("=", "|"));
        }
    }
}

出力:

whoever|[objective] whomever%[possessive] whosever
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
why|[may express] surprise, reluctance, impatience, annoyance, indignation
who|[possessive] whose%[objective] whom

1

PowerShell、85バイト

文字列はハッシュテーブルを使用してマージされます:

%{$h=@{}}{$k,$v=$_-split'\|';$h.$k=($h.$k,$v|?{$_})-join'%'}{$h.Keys|%{$_+'|'+$h.$_}}

PowerShellはを介したstdinリダイレクトをサポートしていないため、デフォルトのI / Oメソッドとして使用されると<想定してGet-Content .\Filename.txt |います。

Get-Content .\Filename.txt | %{$h=@{}}{$k,$v=$_-split'\|';$h.$k=($h.$k,$v|?{$_})-join'%'}{$h.Keys|%{$_+'|'+$h.$_}}

出力

whoever|[objective] whomever%[possessive] whosever
why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
who|[possessive] whose%[objective] whom

1

APL、42文字

{⊃{∊⍺,{⍺'%'⍵}/⍵}⌸/↓[1]↑{(1,¯1↓'|'=⍵)⊂⍵}¨⍵}

APLエンコーディングの1バイトではありません。
ザカリー

0

Sed、55バイト

:a N;:b s/^\([^|]*\)|\([^\n]*\)\n\1|/\1|\2 %/;ta;P;D;tb

テスト走行 :

$ echo """why|[may express] surprise, reluctance, impatience, annoyance, indignation
> whom|[used in] questions, subordination
> whom|[possessive] whose
> whom|[subjective] who
> whoever|[objective] whomever
> whoever|[possessive] whosever
> who|[possessive] whose
> who|[objective] whom""" | sed ':a N;:b s/^\([^|]*\)|\([^\n]*\)\n\1|/\1|\2 %/;ta;P;D;tb'
why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination %[possessive] whose %[subjective] who
whoever|[objective] whomever %[possessive] whosever
who|[possessive] whose %[objective] whom

0

q / kdb +、46バイト

解決:

exec"%"sv v by k from flip`k`v!("s*";"|")0:`:f

例:

q)exec"%"sv v by k from flip`k`v!("s*";"|")0:`:f
who    | "[possessive] whose%[objective] whom"
whoever| "[objective] whomever%[possessive] whosever"
whom   | "[used in] questions, subordination%[possessive] whose%[subjective] who"
why    | "[may express] surprise, reluctance, impatience, annoyance, indignation"

説明:

`:f            // assumes the file is named 'f'
("s*";"|")0:   // read in file, assume it has two columns delimitered by pipe
flip `k`v      // convert into table with columns k (key) and v (value)
exec .. by k   // group on key
"%"sv v        // join values with "%"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.