Побитовое ИЛИ на строках для больших строк в 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") в строку.