Побитовое ИЛИ на строках для больших строк в C#

У меня есть две строки (с 1 и 0) одинаковой длины (<=500) и я хотел бы применить логическое ИЛИ для этих строк.

Как я должен подходить к этому. Я работаю с C#.

Когда я рассматриваю очевидное решение, читая каждый символ и применяя OR | на них мне приходится иметь дело с apx, 250000 строк каждая длиной 500. это убило бы мое выступление.

Производительность - моя главная забота.

Заранее спасибо!

5 ответов

Это самый быстрый способ:

string x="";
string y="";
StringBuilder sb = new StringBuilder(x.Length);
for (int i = 0; i < x.Length;i++ )
{
    sb.Append(x[i] == '1' || y[i] == '1' ? '1' : '0');
}
string result = sb.ToString();

Поскольку было упомянуто, что скорость является важным фактором, было бы лучше использовать побитовые операции.

Посмотрите на таблицу ASCII:

  • Характер '0' является 0x30, или же 00110000 в двоичном
  • Характер '1' является 0x31, или же 00110001 в двоичном

Только последний бит персонажа отличается. Таким образом, мы можем с уверенностью сказать, что выполнение побитового ИЛИ для самих символов даст правильный символ.

Еще одна важная вещь, которую мы можем сделать, это оптимизировать скорость, это использовать StringBuilder, инициализированный до начальной емкости нашей строки. Или даже лучше: мы можем использовать наши StringBuilder для нескольких операций, хотя мы должны обеспечить StringBuilder имеет достаточно возможностей.

С учетом этих оптимизаций мы можем сделать этот метод:

string BinaryStringBitwiseOR(string a, string b, StringBuilder stringBuilder = null)
{
    if (a.Length != b.Length)
    {
        throw new ArgumentException("The length of given string parameters didn't match");
    }

    if (stringBuilder == null)
    {
        stringBuilder = new StringBuilder(a.Length);
    }
    else
    {
        stringBuilder.Clear().EnsureCapacity(a.Length);
    }

    for (int i = 0; i < a.Length; i++)
    {
        stringBuilder.Append((char)(a[i] | b[i]));
    }
    return stringBuilder.ToString();
}

Обратите внимание, что это будет работать для всех побитовых операций, которые вы хотели бы выполнить над строками, вам нужно только изменить | оператор.

Я обнаружил, что это быстрее, чем все предлагаемые решения. Он объединяет элементы из ответов @Gediminas и @Sakura, но использует предварительно инициализированный char[] а не StringBuilder,

В то время как StringBuilder эффективен в управлении памятью, каждый Append операция требует некоторого учета маркера и выполняет больше действий, чем только индекс в массиве.

string x = ...
string y = ...
char[] c = new char[x.Length];
for (int i = 0; i < x.Length; i++)
{
    c[i] = (char)(x[i] | y[i]);
}
string result = new string(c);

У меня есть две строки (с 1 и 0) одинаковой длины (<=500) и я хотел бы применить логическое ИЛИ для этих строк.

Вы можете написать собственный логический оператор или функцию ИЛИ, который принимает два символа в качестве входных данных и выдает результат (например, если хотя бы один из входных символов равен "1", возвращает "1" - в противном случае возвращает "0"). Примените эту функцию к каждому символу в ваших строках.

Вы также можете посмотреть на этот подход. Сначала необходимо преобразовать каждый символ в логическое значение (например, "1" соответствует значению true), выполнить операцию ИЛИ между двумя логическими значениями, преобразовать обратный результат в символ "0" или "1" - в зависимости от того, был ли результат логического ИЛИ ложным или правда соответственно. Затем просто добавьте каждый результат этой операции друг к другу.

Вы можете использовать запрос Linq для архивирования, а затем агрегировать результаты:

var a = "110010";    
var b = "001110";  
var result = a.Zip(b, (i, j) => i == '1' || j == '1' ? '1' : '0')
              .Select(i => i + "").Aggregate((i, j) => i + j);

По сути, метод расширения Zip принимает две последовательности и применяет действие к каждому соответствующему элементу двух последовательностей. Затем я использую Select для приведения char в String и, наконец, я объединяю результаты из последовательности строк ("0" и "1") в строку.

Другие вопросы по тегам