Самый быстрый способ реализовать Дублирующееся Символьное Удаление в Строке (C#)

bash your_script.sh 1>file.log 2>&1

1>file.log сообщает, что оболочка для отправки STDOUT в файл file.log, и 2>&1 говорит этому перенаправлять STDERR (дескриптор файла 2) к STDOUT (дескриптор файла 1).

Примечание: вопросы порядка как liw.fi указанный, 2>&1 1>file.log не работает.

8
задан Welbog 28 August 2009 в 01:58
поделиться

5 ответов

Самый быстрый, как наименьшее количество строк кода:

var s = "nbHHkRvrXbvkn";
var duplicates = s.Where(ch => s.Count(c => c == ch) > 1);
var result = new string(s.Except(duplicates).ToArray()); // = "RrX"

Самый быстрый, как самый быстрый, вероятно, будет примерно таким (не сохраняет порядок):

var h1 = new HashSet<char>();
var h2 = new HashSet<char>();

foreach (var ch in "nbHHkRvrXbvkn")
{
    if (!h1.Add(ch))
    {
        h2.Add(ch);
    }
}

h1.ExceptWith(h2); // remove duplicates

var chars = new char[h1.Count];
h1.CopyTo(chars);
var result = new string(chars); // = "RrX"

Тест производительности

Если сомневаетесь - проверьте это :)

Yuriy Faktorovich's answer        00:00:00.2360900
Luke's answer                     00:00:00.2225683
My 'few lines' answer             00:00:00.5318395
My 'fast' answer                  00:00:00.1842144
21
ответ дан 3 November 2019 в 12:50
поделиться

Это должно быть довольно быстро (с сохранением исходного порядка):

public static string RemoveDuplicates(string source)
{
    HashSet<char> found = new HashSet<char>();
    HashSet<char> dupes = new HashSet<char>();

    foreach (char c in source)
    {
        if (!found.Add(c))
        {
            dupes.Add(c);
        }
    }

    StringBuilder sb = new StringBuilder(source.Length);
    foreach (char c in source)
    {
        if (!dupes.Contains(c))
        {
            sb.Append(c);
        }
    }
    return sb.ToString();
}
4
ответ дан 3 November 2019 в 12:50
поделиться

Вот довольно быстрый заказ на сохранение. Но я был бы немного обеспокоен тем, как LINQ работает с Group и Where:

string s = "nbHHkRvrXbvkn";
Console.WriteLine( 
    s.ToCharArray()
        .GroupBy(c => c)
        .Where(g => g.Count() == 1)
        .Aggregate(new StringBuilder(), (b, g) => b.Append(g.Key)));

Edit: этот вариант превосходит Luke в некоторых случаях все еще медленнее, чем dtb, но сохраняет порядок

private static string MyMethod(string s)
{
    StringBuilder sb = new StringBuilder(s.Length);
    foreach (var g in s.ToCharArray().GroupBy(c => c))
        if (g.Count() == 1) sb.Append(g.Key);

    return sb.ToString();
}
9
ответ дан 3 November 2019 в 12:50
поделиться

This preserves order and, based on my tests, is 4 times faster than using a HashSet. This assumes your character range is 0-255 but you can extend that easily. If you're planning on using this in a loop, move the int[] c = new int[255]; out and in the function do an Array.Clear(c,0,255).


        private static string RemoveDuplicates(string s)
        {
            int[] c = new int[255];
            for (int i = 0; i < s.Length; i++)
            {
                c[s[i]]++;
            }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.Length; i++)
            {
                if (c[s[i]] == 1) sb.Append(s[i]);
            }
            return sb.ToString();
        }
2
ответ дан 3 November 2019 в 12:50
поделиться

Этот алгоритм является общим, может быть применен к любому языку

  1. создать карту (HashTable) char-> int, которая содержит счетчик каждого найденного символа, изначально пустой
  2. просканируйте строку один раз, чтобы заполнить карту.
  3. создайте новую пустую строку, которая будет содержать вывод, возможно, вам понадобится использовать StringBuilder.
  4. просканируйте строку (или карту, в зависимости от того, что короче) копирование только символов, в которых встречается 1, в строку вывода / StringBuilder
0
ответ дан 3 November 2019 в 12:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: