문자열에서 중복 제거


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

자바 8, 117110 바이트

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

MATL , 19 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

펄 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. 두 번째 두 단어가 제대로 제거 할뿐만 아니라, 제거 be두 번째 이후에 will어떤 이유로.
Kevin Cruijssen

1
@KevinCruijssen Hmmm, 왜 그런 일이 일어나고 있는지 알 수 있습니다. 나는 내일 점심을 제대로 보려고 노력할 것이다. 그러나 나는 지금 +4의 비용으로 고쳤다. 알려 줘서 고마워!
Dom Hastings

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

@TonHospel Ahh, lcparens없이 호출 하려고하는 동안 시간을 ​​보냈습니다 . 대박! 그리고 배열에 대해 정규 표현식을 사용하는 것이 훨씬 좋습니다. 감사합니다! 나는 당신의 모든 팁을 기억하는 데 어려움을 겪고 있습니다!
Dom Hastings

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

Stax , 21 바이트 CP437

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

압축을 풀 때 25 바이트

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

결과는 배열입니다. Stax의 편리한 출력은 라인 당 하나의 요소입니다.

온라인으로 실행하고 디버그하십시오!

설명

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

펄 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

펄 5 , 50 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

자바 스크립트 (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 네,하지만 주요 거래는 몸을 골프하기 때문에 함수의 정의를 골프하는 것에 대해 정말로 마음에 듭니다. 하지만 들으 :) 좋은 팁을 먹으 렴
DanielIndie

1

자바 스크립트 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=.
Martin Ender

PPCG에 오신 것을 환영합니다! 슬프게도 다른 사건이 관련되면 실패합니다.
얽히고 설킨

그렇지 않다면 이것을 67 바이트
Shaggy

@MartinEnder 팁 주셔서 감사합니다!
Ian

@Shaggy는 입력 배열을 객체로 사용하는 것은 내가 생각하지 않은 흥미로운 아이디어입니다. 사건 문제를 해결하려고 노력할 것입니다.
Ian

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

자바 스크립트, 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
.*,

-14 바이트 덕분에 @Neil , 버그 수정의 경우 +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
작성된 것처럼 첫 번째 줄 +i`((.+),.*\2.* )\2( |$)과 두 번째 줄을 단순화 할 수는 $1있지만 often,he intended to keep ten geese어쨌든 코드가 실패하는 것을 알 수 있습니다 .
Neil

@Neil -14 골프에 감사하고 +1로 버그를 수정했습니다.
Kevin Cruijssen

... 이것이 원래의 테스트 사례 중 하나에서 실패한다는 것을 제외하고는 ...
Neil

@Neil Ah 죄송합니다. +4 바이트로 다시 고정되었습니다.
Kevin Cruijssen

글쎄, 좋은 소식은 \b대신에 사용할 수 있다고 생각 (^|,)하지만 나쁜 소식은 필요한 것이라고 생각합니다 \b\3\b(아직 적합한 테스트 사례를 고안하지는 않았습니다).
Neil

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로하고 중복 문자열 중 하나를 두 번째 요소로 하여 스택에 있습니다.

("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 줄 이상입니다. 첫 번째 줄은 단어 목록이고 두 번째 줄은 "문장"입니다. "단어"와 "단어"는 첨부 된 문장 부호와 동일한 것으로 간주되지 않습니다. 구두점 요구 사항이 있으면 더 재미있는 문제 가 될 수 있습니다.



0

파이썬 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라는 하나의 오브젝트가이 함수에 전달됩니다. 이 오브젝트에는 발견 된 발생에 대한 정보가 있습니다. 이 사건에 대한 색인에 관심이 있습니다.start() 또는end() 기능은 기능 . 후자는 짧아서 사용됩니다.

처음 나오는 단어의 대체를 제외하기 위해 다른 정규식 검색 기능을 사용하여 정확히 하나를 시작한 다음 동일한 것을 사용하여 색인을 비교했습니다. end()

플래그 re.I는 짧은 버전입니다re.IGNORECASES

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.