文字列から重複を削除する


17

この控えめなStackOverflow質問に触発されました。

アイデアはシンプルです。文字列と文字列の配列を指定すると、最初の文字列以外の入力文字列から、配列内の単語のインスタンスをすべて削除します(大文字と小文字は無視します)。単語は、単語の一部ではなく、入力文字列内の単語全体と一致する必要があります。

たとえば、"A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat", ["cat", "mat"]出力する必要があります"A cat called matt sat on a mat and wore a hat A called matt sat on a and wore a hat"

入力

  • 入力は、文字列、文字列の配列、または入力文字列が最初の要素である文字列の配列として取得できます。これらのパラメーターはどちらの順序でもかまいません。
  • 入力文字列は、スペースで区切られた文字列のリストとして使用できません。
  • 入力文字列には、先頭、末尾、または連続するスペースはありません。
  • すべての入力には、スペースを含む入力文字列を除き、文字[A-Za-z0-9]のみが含まれます。
  • 入力配列は空であるか、入力文字列にない単語を含んでいる可能性があります。

出力

  • 出力は、関数からの戻り値にするか、STDOUTに出力できます。
  • 出力は、元の文字列と同じ大文字である必要があります

テストケース

the blue frog lived in a blue house, [blue] -> the blue frog lived in a house
he liked to read but was filled with dread wherever he would tread while he read, [read] -> he liked to read but was filled with dread wherever he would tread while he
this sentence has no matches, [ten, cheese] -> this sentence has no matches
this one will also stay intact, [] -> this one will also stay intact
All the faith he had had had had no effect on the outcome of his life, [had] -> All the faith he had no effect on the outcome of his life
5 times 5 is 25, [5, 6] -> 5 times is 25
Case for different case, [case] -> Case for different
the letters in the array are in a different case, [In] -> the letters in the array are a different case
This is a test Will this be correct Both will be removed, [this,will] -> This is a test Will be correct Both be removed

これはコードゴルフであるため、最小バイトカウントが勝ちです!

回答:


9

R、84バイト

function(s,w,S=el(strsplit(s," ")),t=tolower)cat(S[!duplicated(x<-t(S))|!x%in%t(w)])

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

でもないチャレンジで100バイト未満ですか?

説明:

文字列を単語に分割したら、次のものを除外する必要があります

  1. 複製と
  2. w

または、頭の上でそれを回して、あるものを維持する

  1. 単語の最初の出現OR
  2. ではありませんw

duplicatedきちんと最初の発生でないものの論理的インデックスを返し、そう!duplicated()最初の発生であるもののリターンインデックス、およびx%in%wの論理インデックスを返しxているもののw。きちんとした。


6

Java 8、117 110バイト

a->s->{for(String x:a)for(x="(?i)(.*"+x+".* )"+x+"( |$)(.*)";s.matches(x);s=s.replaceAll(x,"$1$3"));return s;}

説明:

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

a->s->{                // Method with String-array and String parameters and String return
  for(String x:a)      //  Loop over the input-array
    for(x="(?i)(.*"+x+".* )"+x+"( |$)(.*)";
                       //   Regex to match
        s.matches(x);  //   Inner loop as long as the input matches this regex
      s=s.replaceAll(x,"$1$3")); 
                       //    Replace the regex-match with the 1st and 3rd capture groups
  return s;}           //  Return the modified input-String

正規表現の追加説明:

(?i)(.*"+x+".* )"+x+"( |$)(.*)   // Main regex to match:
(?i)                             //  Enable case insensitivity
    (                            //  Open capture group 1
     .*                          //   Zero or more characters
       "+x+"                     //   The input-String
            .*                   //   Zero or more characters, followed by a space
               )                 //  End of capture group 1
                "+x+"            //  The input-String again
                     (           //  Open capture group 2
                       |$        //   Either a space or the end of the String
                         )       //  End of capture group 2
                          (      //  Open capture group 3
                           .*    //   Zero or more characters
                             )   //  End of capture group 3

$1$3                             // Replace the entire match with:
$1                               //  The match of capture group 1
  $3                             //  concatted with the match of capture group 3

4

MATL19 18バイト

"Ybtk@kmFyfX<(~)Zc

入力は、文字列のセル配列、次に文字列です。

オンラインでお試しください!または、すべてのテストケースを確認します

使い方

"        % Take 1st input (implicit): cell array of strings. For each
  Yb     %   Take 2nd input (implicit) in the first iteration: string; or
         %   use the string from previous iteration. Split on spaces. Gives
         %   a cell array of strings
  tk     %   Duplicate. Make lowercase
  @k     %   Push current string from the array taken as 1st input. Make
         %   lowercase
  m      %   Membership: gives true-false array containing true for strings
         %   in the first input argument that equal the string in the second
         %   input argument
  F      %   Push false
  y      %   Duplicate from below: pushes the true-false array again
  f      %   Find: integer indices of true entries (may be empty)
  X<     %   Minimum (may be empty)
  (      %   Assignment indexing: write false in the true-false array at that
         %   position. So this replaces the first true (if any) by false
  ~      %   Logical negate: false becomes true, true becomes false
  )      %   Reference indexing: in the array of (sub)strings that was
         %   obtained from the second input, keep only those indicated by the
         %   (negated) true-false array
  Zc     %   Join strings in the resulting array, with a space between them
         % End (implicit). Display (implicit)

3

Perl 5、49バイト

@B=<>;$_=join$",grep!(/^$_$/xi~~@B&&$v{+lc}++),@F

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

@TonHospelのおかげで9(!!)バイト節約できました


1
これはThis is a test Will this be correct Both will be removed+で失敗するようthis willです。2番目の2つの単語は正しく削除されますが、何らかの理由でbe2番目以降の単語も削除されwillます。
ケビンクルーッセン

1
@KevinCruijssenうーん、それが今なぜ起こっているのかわかります。明日は昼食を適切に見てみますが、今のところ+4の費用で修正しました。知らせてくれてありがとうございます!
ドムヘイスティングス

49の場合:@B=<>;$_=join$",grep!(/^$_$/xi~~@B&&$v{+lc}++),@F
トンホスペル

@TonHospelああ、無言lcで呼ばれるようにしようとしばらくしました。驚くばかり!そして、配列に対して正規表現を使用する方がはるかに優れてます、ありがとう!あなたのすべてのヒントを思い出すのに苦労します!
ドムヘイスティングス

2

Pyth、27バイト

jdeMf!}r0eT@mr0dQmr0dPT._cz

オンラインで試す

説明

jdeMf!}r0eT@mr0dQmr0dPT._cz
                          z  Take the string input.
                       ._c   Get all the prefixes...
    f    eT@                 ... which end with something...
     !}         Q    PT      ... which is not in the input and the prefix...
       r0   mr0d mr0d        ... case insensitive.
jdeM                         Join the ends of each valid prefix.

大文字と小文字を区別しないチェックの10バイトを削減できると確信していますが、その方法はわかりません。


2

スタックス、21 バイトCP437

åìøΓ²¬$M¥øHΘQä~╥ôtΔ♫╟

解凍すると25バイト、

vjcm[]Ii<;e{vm_]IU>*Ciyj@

結果は配列です。Staxの便利な出力は、1行に1つの要素です。

オンラインで実行してデバッグします!

説明

vj                           Convert 1st input to lowercase and split at spaces,
  c                          Duplicate at the main stack
   m                         Map array with the rest of the program 
                                 Implicitly output
    []I                      Get the first index of the current array element in the array
       i<                    Test 1: The first index is smaller than the iteration index
                                 i.e. not the first appearance
         ;                   2nd input
          {vm                Lowercase all elements
             _]I             Index of the current element in the 2nd input (-1 if not found)
                U>           Test 2: The index is non-negative
                                 i.e. current element is a member of the 2nd input
                  *C         If test 1 and test 2, drop the current element
                                 and go on mapping the next
                    iyj@     Fetch the corresponding element in the original input and return it as the mapped result
                                 This preserves the original case

2

Perl 6、49バイト

->$_,+w{~.words.grep:{.lcw».lc||!(%){.lc}++}}

試して

拡張:

->              # pointy block lambda
  $_,           # first param 「$_」 (string)
  +w            # slurpy second param 「w」 (words)
{

  ~             # stringify the following (joins with spaces)

  .words        # split into words (implicit method call on 「$_」)

  .grep:        # take only the words we want

   {
     .lc        # lowercase the word being tested
               # is it not an element of
     w».lc      # the list of words, lowercased

     ||         # if it was one of the words we need to do a secondary check

     !          # Boolean invert the following
                # (returns true the first time the word was found)

     (
       %        # anonymous state Hash variable
     ){ .lc }++ # look up with the lowercase of the current word, and increment
   }
}

2

Perlの550の、48バイト

含み+1のために-p

STDINの個別の行に、ターゲット文字列と各フィルターワードを指定します。

perl -pe '$"="|";s%\b(@{[<>]})\s%$&x!$v{lc$1}++%iegx;chop';echo
This is a test Will this be correct Both will be removed
this
will
^D
^D

chop最後の言葉が削除される場合にのみ、末尾のスペースを修正するために必要とされています

コードだけ:

$"="|";s%\b(@{[<>]})\s%$&x!$v{lc$1}++%iegx;chop

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


1

JavaScript(ES6)、98バイト

s=>a=>s.split` `.filter(q=x=>(q[x=x.toLowerCase()]=eval(`/\\b${x}\\b/i`).test(a)<<q[x])<2).join` `

1

K4、41バイト

解決:

{" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}

例:

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat";("cat";"mat")]
"A cat called matt sat on a mat and wore a hat A called matt sat on a and wore a hat"

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["Case for different case";enlist "case"]
"Case for different"

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["the letters in the array are in a different case";enlist "In"]
"the letters in the array are a different case"

q)k){" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x}["5 times 5 is 25";(1#"5";1#"6")]
"5 times is 25"

説明:

空白で分割し、両方の入力を小文字にし、一致を探し、最初の出現を除くすべてを削除し、文字列を結合します。

{" "/:x_/y@>y:,/1_'&:'(_y)~/:\:_x:" "\:x} / the solution
{                                       } / lambda with implicit x & y args
                                  " "\:x  / split (\:) on whitespace " "
                                x:        / save result as x
                               _          / lowercase x
                          ~/:\:           / match (~) each right (/:), each left (\:)
                      (_y)                / lowercase y
                   &:'                    / where (&:) each ('), ie indices of matches
                1_'                       / drop first of each result
              ,/                          / flatten
            y:                            / save result as y
         y@>                              / descending indices (>) apply (@) to y
      x_/                                 / drop (_) from x
 " "/:                                    / join (/:) on whitespace " "

1

JavaScript(Node.js)、75バイト

f=(s,a)=>a.map(x=>s=s.replace(eval(`/\\b${x}\\b */ig`),s=>i++?"":s,i=0))&&s

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


1
これは再帰的な関数ではないためf=、バイトカウントにを含める必要はありません。また、パラメーターをカリー化し、で置き換え(s,a)=>s=>a=>から関数を呼び出して、バイトを保存することもできますf(s)(a)
シャギー

@Shaggyはい、しかし、主な取引は体をゴルフすることなので、関数の定義をゴルフすることを本当に気にしています。thxそれは良いヒントです:)
DanielIndie

1

JavaScript ES6、78バイト

f=(s,a,t={})=>s.split` `.filter(w=>a.find(e=>w==e)?(t[w]?0:t[w]=1):1).join` `

使い方:

f=(s,a,t={})=> // Function declaration; t is an empty object by default
s.split` ` // Split the string into an array of words
.filter(w=> // Declare a function that, if it returns false, will delete the word
  a.find(e=>w==e) // Returns undeclared (false) if the word isn't in the list
  ?(t[w]?0 // If it is in the list and t[w] exists, return 0 (false)
    :t[w]=1) // Else make t[w] exist and return 1 (true)
  :1) // If the word isn't in the array, return true (keep the word for sure)
.join` ` // Rejoin the string

2
PPCGへようこそ!f再帰呼び出しに関数名を使用していないため、名前のない関数も有効なサブミットになるため、をドロップして2バイトを節約できますf=
マーティンエンダー

PPCGへようこそ!悲しいことに、さまざまなケースが関係する場合、これは失敗します。
シャギー

それがなかったら、これを67バイトに
Shaggy

@MartinEnderヒントをありがとう!
イアン

入力配列をオブジェクトとして使用する@Shaggyは、私が考えていなかった興味深いアイデアです。ケースの問題を解決しようとします。
イアン

0

PowerShell v3以降、104バイト

Param($s,$w)$w|?{$_-and$s-match($r="\b$_(?: |$)")}|%{$h,$t=$s-split$r;$s="$h$($Matches.0)$(-join$t)"};$s

1バイトのコストで、に置き換え$Matches.0てPS 2.0で実行できます$Matches[0]

ロングバージョン:

Param($s, $w)
$w | Where-Object {$_ -and $s -match ($r = "\b$_(?: |$)")} |    # Process each word in the word list, but only if it matches the RegEx (which will be saved in $r).
    ForEach-Object {                                            # \b - word boundary, followed by the word $_, and either a space or the end of the string ($)
        $h, $t = $s -split $r                                   # Split the string on all occurrences of the word; the first substring will end up in $h(ead), the rest in $t(ail) (might be an array)
        $s = "$h$($Matches.0)$(-join $t)"                       # Create a string from the head, the first match (can't use the word, because of the case), and the joined tail array
    }
$s                                                              # Return the result

使用法
Whatever.ps1として保存し、文字列と単語を引数として呼び出します。複数の単語を渡す必要がある場合、単語を@()でラップする必要があります。

.\Whatever.ps1 -s "A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat" -w @("cat", "mat")

ファイルなしの代替(PSコンソールに直接貼り付けることができます):
スクリプトをScriptBlock(中括弧内)として変数に保存し、そのInvoke()メソッドを呼び出すか、Invoke-Commandで使用します。

$f={Param($s,$w)$w|?{$_-and$s-match($r="\b$_(?: |$)")}|%{$h,$t=$s-split$r;$s="$h$($Matches.0)$(-join$t)"};$s}
$f.Invoke("A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat", @("cat", "mat"))
Invoke-Command -ScriptBlock $f -ArgumentList "A cat called matt sat on a mat and wore a hat A cat called matt sat on a mat and wore a hat", @("cat", "mat")

0

Javascript、150バイト

s=(x, y)=>{let z=new Array(y.length).fill(0);let w=[];for(f of x)(y.includes(f))?(!z[y.indexOf(f)])&&(z[y.indexOf(f)]=1,w.push(f)):w.push(f);return w}

ゴルフの問題(いくつかのヒントについては他のJSソリューションをご覧ください)に加えて、これは最初の入力を単語の配列として取得し、チャレンジ仕様で許可されていない単語の配列を出力します。さまざまなケースが関係している場合も失敗します。
シャギー

@Shaggy「出力は関数からの戻り値のいずれかです」これは関数から値を返すように見えますか?
aimorris

0

クリーン153の 142 138 134バイト

import StdEnv,StdLib,Text
@ =toUpperCase
$s w#s=split" "s
=join" "[u\\u<-s&j<-[0..]|and[i<>j\\e<-w,i<-drop 1(elemIndices(@e)(map@s))]]

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

関数を定義し、$ :: String [String] -> Stringほとんど文字通りチャレンジが説明することを行います。各ターゲットワードについて、最初のオカレンス以降のすべてのオカレンスを検索して削除します。


0

網膜、46 37バイト

+i`(^|,)((.+),.*\3.* )\3( |$)
$2
.*,

@Neilのおかげで-14バイト、バグ修正のために+5バイト。

word1,word2,word3,sentence複数行入力(入力の使い方が異なる)の方法がわからないため、形式で入力します。

説明:

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

+i`(^|,)((.+),.*\3.* )\3( |$)   Main regex to match:
+i`                              Enable case insensitivity
   (^|,)                          Either the start of the string, or a comma
        (                         Open capture group 2
         (                         Open capture group 3
          .+                        1 or more characters
            )                      Close capture group 3
             ,                     A comma
              .*                   0 or more characters
                \3                 The match of capture group 3
                  .*               0 or more characters, followed by a space
                     )            Close capture group 2
                      \3          The match of capture group 2 again
                        ( |$)     Followed by either a space, or it's the end of the string
$2                              And replace everything with:
                                 The match of capture group 2

.*,                             Then get everything before the last comma (the list)
                                 and remove it (including the comma itself)

1
書かれているように、1行+i`((.+),.*\2.* )\2( |$)目と2 行目を簡略化でき$1ますが、often,he intended to keep ten geeseとにかくコードが失敗することに気付きます。
ニール

@Neil -14ゴルフに感謝し、+ 1でバグを修正しました。
ケビンCruijssen

...これは今、元のテストケースの一つ...に失敗したことを除いて
ニール

@Neil Ah oops .. +4バイトで再び修正。
ケビンクルーッセン

さて、良いニュースはの\b代わりに使用できると思います(^|,)が、悪いニュースは必要だと思います\b\3\b(まだ適切なテストケースを考案していません)。
ニール

0

、98バイト

func[s w][foreach v w[parse s[thru[any" "v ahead" "]any[to remove[" "v ahead[" "| end]]| skip]]]s]

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

f: func [s w][ 
    foreach v w [                   ; for each string in the array
        parse s [                   ; parse the input string as follows:
            thru [                  ; keep everything thru: 
                any " "             ; 0 or more spaces followed by
                v                   ; the current string from the array followed by
                ahead " "           ; look ahead for a space
            ]
            any [ to remove [       ; 0 or more: keep to here; then remove: 
                " "                 ; a space followed by 
                v                   ; the current string from the array
                ahead [" " | end]]  ; look ahead for a space or the end of the string
            | skip                  ; or advance the input by one 
            ]
        ]
    ]
    s                               ; return the processed string 
]

0

、13バイト

wüöVËm_Ṗ3+⁰ew

引数として文字列のリストと単一の文字列をこの順序で取ります。リストに重複がないと仮定します。 オンラインでお試しください!

説明

wüöVËm_Ṗ3+⁰ew  Inputs: list of strings L (explicit, accessed with ⁰), string S (implicit).
               For example, L = ["CASE","for"], s = "Case for a different case".
            w  Split S on spaces: ["Case","for","a","different","case"]
 ü             Remove duplicates wrt an equality predicate.
               This means that a function is called on each pair of strings,
               and if it returns a truthy value, the second one is removed.
  öVËm_Ṗ3+⁰e    The predicate. Arguments are two strings, say A = "Case", B = "case".
           e    Put A and B into a list: ["Case","case"]
         +⁰     Concatenate with L: ["CASE","for","Case","case"]
       Ṗ3       All 3-element subsets: [["CASE","for","Case"],["CASE","for","case"],
                                        ["CASE","Case","case"],["for","Case","case"]]
  öV            Does any of them satisfy this:
    Ë            All strings are equal
     m_          after converting each character to lowercase.
                In this case, ["CASE","Case","case"] satisfies the condition.
               Result: ["Case","for","a","different"]
w              Join with spaces, print implicitly.

0

最小、125バイト

=a () =b a 1 get =c a 0 get " " split
(:d (b d in?) ((c d in?) (d b append #b) unless) (d b append #b) if) foreach
b " " join

入力はquot、最初の要素として入力文字quot列、2番目の要素として重複文字列のa を持つスタック上にあります。

("this sentence has no matches" ("ten" "cheese"))


0

AWK、120バイト

NR%2{for(;r++<NF;)R[tolower($r)]=1}NR%2==0{for(;i++<NF;$i=$(i+s))while(R[x=tolower($(i+s))])U[x]++?++s:i++;NF-=s}NR%2==0

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

「空白の削除」の部分は、私が最初に考えていたよりも少し難しくしました。フィールドを""に設定すると、フィールドは削除されますが、余分なセパレータが残ります。

TIOリンクには、複数のエントリを許可するために28バイトが追加されています。

入力は2行にわたって与えられます。最初の行は単語のリストであり、2行目は「文」です。「単語」と「単語」は、添付の句読点と同じとは見なされないことに注意してください。句読点の要件があると、これはさらに楽しい問題になる可能性があります。



0

Python 2、140バイト

from re import*
p='\s?%s'
S,A=input()
for a in A:S=sub(p%a,lambda s:s.end()==search(p%a,S,flags=I).end()and s.group()or'',S,flags=I)
print S

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

説明:

re.sub(..)引数として、置換文字列の代わりに関数を取ることができます。それで、ここにいくつかの派手なラムダがあります。パターンが発生するたびに関数が呼び出され、この関数にmatchobjectという1つのオブジェクトが渡されます。このオブジェクトには、発生の発生に関する情報があります。私はによって取得することができ、この出現のインデックス、に興味start()end()機能。後者は短いので使用されます。

単語の最初の出現の置換を除外するために、別の正規表現検索関数を使用して正確に最初のものを取得し、同じものを使用してインデックスを比較しました end()

フラグre.Iはの短いバージョンですre.IGNORECASES

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.