Видалення унікальних елементів із рядка


12

Я підійшов до цього питання, тому що, здається, дуже часто використовуються випадки пошуку унікальних символів у рядку. Але що робити, якщо ми хочемо їх позбутися?

Вхід містить лише малі алфавіти. Використовуються лише літери від a до z. Довжина вводу може бути від 1 до 1000 символів.

Приклад:
вхід: helloworld
вихід: llool

Мета: Найкоротший код виграє
Мова: Будь-яка з перших 20 мов TIOBE

Відповіді:


7

Perl, 28 24 символи (включає 1 для параметра "p")

s/./$&x(s!$&!$&!g>1)/eg

Використання:

> perl -pe 's/./$&x(s!$&!$&!g>1)/eg'
helloworld
llool

Спочатку я думав, що можу це зробити з негативним поглядом вперед та негативним оглядом позаду, але виявляється, що негативні видимості повинні мати фіксовану довжину. Тому я пішов на вкладені регулярні вирази. Завдяки моб за $&чайові.


+1. Я наївно думав, що можу відповісти на цю річ моєю відповіді Рубі.
Стівен Румбальський

Я спробував це на китайському тексті, і це не зробило трюку. = (
ixtmixilix

@ixtmixilix - тоді запустіть perl з -CDSопцією
mob

@ixtmixilix Я не знаю достатньо про Unicode та підтримку Perl, щоб запропонувати спосіб змусити його працювати з китайським текстом. На щастя для мене питання говорить лише про малі регістри від a до z.
Гарет

1
Замінити всі $1з , $&і ви можете втратити пару пар дужок.
моб

12

(GolfScript, 15 13 символів)

:;{.;?);>?)},

GolfScript - не один з перших 20, але кодовий гольф без GolfScript ... ( запустіть його самостійно )

Попередня версія: ( запустіть сценарій )

1/:;{;\-,;,(<},

1
:;? Ви навмисно намагаєтесь заплутати новачків, чи не так? ;)
Пітер Тейлор

@PeterTaylor Ви маєте рацію. Я мав би обрати таке )- це зробило б це усмішкою тоді :). На жаль, я не знайшов способу навіть усунути цифру 1. (Примітка для новачків GolfScript: будь-який ;код у коді можна замінити на x(або будь-яку іншу букву чи цифру - або будь-який символ, який не використовується в сценарії інакше). У цьому спеціальному випадку ;це лише назва змінної - і не має значення "поп і відкинути". У GolfScript майже всі лексеми так само є змінними, а використання попередньо визначених символів - це чудовий спосіб зробити сценарії ще більш нечитабельними для сторонніх людей ;-).)
Говард

Ще одне 13- :a{]a.@--,(},
чаркове

7

J, 12 символів

Ввівши дійсну відповідь Perl, ось недійсна відповідь (мова не в TIOBE верхній 20).

a=:#~1<+/@e.

Використання:

   a 'helloworld'
llool

Оголошує дієслово, aяке видає лише не унікальні елементи.



4

Рубін 46 40 36

gets.chars{|c|$><<c if$_.count(c)>1}

Ви можете зберегти 4 символи, якщо ви встромляєте їх sі використовуєте $_для другого вигляду (простір перед цим не потрібний).
Говард

@Howard: Хороший улов. Дякую. У мене з Рубі майже нульовий досвід.
Стівен Румбальський

2

Perl 44

$l=$_;print join"",grep{$l=~/$_.*$_/}split""

Виконання:

perl -lane '$l=$_;print join"",grep{$l=~/$_.*$_/}split""' <<< helloworld
llool


2

Python 2.7 ( 52 51), Python 3 (52)

Я не очікував, що це буде так коротко.

2.7: a=raw_input();print filter(lambda x:a.count(x)>1,a)

3,0: a=input();print''.join(i for i in a if a.count(x)>1)

raw_input(): зберігає введення як рядок ( input()= eval(raw_input()))
(Python 3.0: input()перетворено raw_input())

filter(lambda x:a.count(x)>1,a): Фільтруйте всі символи всередині, aякщо вони знайдені aбільше одного разу ( a.count(x)>1).


Якщо ви використовуєте python 3 замість цього, ви можете використовувати, input()а не raw_input(). Хоча вам потрібно додати один символ для дужки, оскільки printце функція в python 3.
Strigoides

@Strigoides: Я додав фрагмент коду Python 3 до своєї відповіді.
beary605

Фільтр Python 3 повертає ітератор ... Вам потрібно буде це зробити''.join(...)
JBernardo

@JBernardo: :( Dang. Дякую за повідомлення. Як бачите, я не використовую 3.0.
beary605

2

sed і coreutils (128)

Звичайно, це не є частиною списку TIOBE, але це весело (-:

<<<$s sed 's/./&\n/g'|head -c -1|sort|uniq -c|sed -n 's/^ *1 (.*)/\1/p'|tr -d '\n'|sed 's:^:s/[:; s:$:]//g\n:'|sed -f - <(<<<$s)

Версія для де-гольфу:

s=helloworld
<<< $s sed 's/./&\n/g'        \
| head -c -1                  \
| sort                        \
| uniq -c                     \
| sed -n 's/^ *1 (.*)/\1/p'   \
| tr -d '\n'                  \
| sed 's:^:s/[:; s:$:]//g\n:' \
| sed -f - <(<<< $s)

Пояснення

Перший sed перетворює вхід в один символ на рядок. У другому седі знаходять символи, які трапляються лише один раз. Третій sed пише сценарій sed, який видаляє унікальні символи. Останній sed виконує створений сценарій.


2

Брахілог (v2), 8 байт

⊇.oḅlⁿ1∧

Спробуйте в Інтернеті!

Подання функції Технічно не конкурує, оскільки питання має обмеження щодо того, які мовні змагання дозволені до змагань (однак, кілька інших відповідей уже ігнорували обмеження).

Пояснення

⊇.oḅlⁿ1∧
⊇         Find {the longest possible} subset of the input
  o       {for which after} sorting it,
   ḅ        and dividing the sorted input into blocks of identical elements,
    lⁿ1     the length of a resulting block is never 1
 .     ∧  Output the subset in question.

Чому ви CW всі свої рішення?
Кошлатий

1
@Shaggy: а) тому що мені добре з іншими людьми, які їх редагують, б) щоб уникнути завоювання репутації, якщо вони отримали перевагу. Взагалі, я вважаю, що гміфіфікація Stack Exchange є величезною шкодою для сайту - іноді існує негативна кореляція між діями, які ви можете вжити, щоб поліпшити представництво, та діями, які ви можете вжити, щоб фактично покращити сайт. Крім того, знаходячись на високому рівні репутації відстій; на веб-сайті постійно тягнуть вас до виконання завдань адміністратора, і все, що ви робите, - це тупий інструмент (наприклад, коли у вас є низька кількість представників, ви можете запропонувати редагувати, а при високому повторі це просто вимушене пройти).
ais523


1

Пітон (56)

Ось ще одна (на кілька символів довше) альтернатива Python:

a=raw_input();print''.join(c for c in a if a.count(c)>1)

Якщо ви приймаєте вихід у вигляді списку (наприклад ['l', 'l', 'o', 'o', 'l']), ми можемо звести його до 49 символів:

a=raw_input();print[c for c in a if a.count(c)>1]

Гей, >1це гарна ідея! Чи можу я включити це у своє рішення?
beary605

@ beary605 Звичайно, взагалі немає проблем - простий спосіб обрізати персонажа: D
Аршаджі

1

Математика 72 63

Гаразд, Mathematica не входить в топ-20 мов, але я все-таки вирішив приєднатися до вечірки.

x - це рядок введення.

"" <> Select[y = Characters@x, ! MemberQ[Cases[Tally@y, {a_, 1} :> a], #] &]


1

C # - 77 символів

Func<string,string>F=s=>new string(s.Where(c=>s.Count(d=>c==d)>1).ToArray());

Якщо ви приймаєте вихід як масив, він зводиться до 65 символів:

Func<string,char[]>F=s=>s.Where(c=>s.Count(d=>c==d)>1).ToArray();

1

Окамль, 139 133

Використовує ExtLib's ExtString.String

open ExtString.String
let f s=let g c=fold_left(fun a d->a+Obj.magic(d=c))0 s in replace_chars(fun c->if g c=1 then""else of_char c)s

Версія без гольфу

open ExtString.String
let f s =
  let g c =
    fold_left
      (fun a c' -> a + Obj.magic (c' = c))
      0
      s
  in replace_chars
  (fun c ->
    if g c = 1
    then ""
    else of_char c)
  s

Функція gповертає кількість випадків c у рядку s. Функція fзамінює всі знаки або порожнім рядком, або рядком, що містить знак, залежно від кількості випадків. Редагувати: Я скоротив код на 6 символів, зловживав внутрішнім поданням bools :-)

Ой, і ocaml 0 в індексі TIOBE ;-)


f *** індекс TIOBE.
ixtmixilix

Я згоден. Також спасибі за нагороду. Тепер я можу коментувати :-)
ReyCharles


1

Java 8, 90 байт

s->{for(char c=96;++c<123;s=s.matches(".*"+c+".*"+c+".*")?s:s.replace(c+"",""));return s;}

Пояснення:

Спробуйте в Інтернеті.

s->{                         // Method with String as both parameter and return-type
  for(char c=96;++c<123;     //  Loop over the lowercase alphabet
    s=s.matches(".*"+c+".*"+c+".*")?
                             //   If the String contains the character more than once
       s                     //    Keep the String as is
      :                      //   Else (only contains it once):
       s.replace(c+"",""));  //    Remove this character from the String
  return s;}                 //  Return the modified String

1

PowerShell , 59 байт

"$args"-replace"[^$($args|% t*y|group|?{$_.Count-1}|% n*)]"

Спробуйте в Інтернеті!

Менше гольфу:

$repeatedСhars=$args|% toCharArray|group|?{$_.Count-1}|% name
"$args"-replace"[^$repeatedСhars]"

Примітка: $repeatedCharsце масив. За замовчуванням Powershell приєднує елементи масиву за допомогою пробілу, перетворюючи масив у рядок. Отже, регулярне вираження містить пробіли (У цьому прикладі [^l o]). Пробіли не впливають на результат, оскільки рядок введення містить лише літери.


1

APL (Dyalog Extended) , 8 байт SBCS

Функція анонімного мовчазного префікса.

∊⊢⊆⍨1<⍧⍨

Спробуйте в Інтернеті!

⍧⍨ selfie з підрахунком (кількість вхідних елементів аргументу в сам аргумент)

1< Булева маска там, де вона менша за це

⊢⊆⍨ розділіть аргумент за допомогою цієї маски (запуск нового розділу на 1s та видалення на 0s)

ϵ nlist (згладити)



1

R , 70 байт

a=utf8ToInt(scan(,''));intToUtf8(a[!a%in%names(table(a)[table(a)<2])])

Спробуйте в Інтернеті!

Погана спроба, навіть із мови 20 кращих TIOBE. Я знаю, що щось можна зробити щодо другої половини, але на даний момент будь-які гольфи рятуються від мене.




0

PHP - 137

Код

implode('',array_intersect(str_split($text),array_flip(array_filter(array_count_values(str_split($text)),function($x){return $x>=2;}))));

Нормальний код

$text   = 'helloworld';
$filter = array_filter(array_count_values(str_split($text)), function($x){return $x>=2;});
$output = implode('',array_intersect(str_split($text),array_flip($filter)));

echo $output;

0

PHP - 83 78

<?for($a=$argv[1];$i<strlen($a);$r[$a[$i++]]++)foreach($ras$k=>$c)if($c>1)echo$k

Поліпшена версія:

<?for($s=$argv[1];$x<strlen($s);$c=$s[$x++]) echo substr_count($s,$c)>1?$c:'';

Звичайно, для цього потрібно вимкнути повідомлення

Редагувати: Вдосконалення надихнуло @hengky mulyono

Мені так погано в кодегольфі :)


0

C ++, 139 байт

string s;cin>>s;string w{s}; auto l=remove_if(begin(s),end(s),[&w](auto&s){return count(begin(w),end(w),s)==1;});s.erase(l,end(s));cout<<s;

неозорений:

#include <algorithm>
#include <string>
#include <iostream>

int main() {
  using namespace std;
  string s;
  cin >> s;
  const string w{s};
  auto l = remove_if(begin(s), end(s), [&w](auto& s) {
                                         return count(begin(w), end(w), s) == 1;
                                       });
  s.erase(l, end(s));
  cout << s;
  return 0;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.