Разобрать идентификаторы из входной строки в длинное число, используя Span < T > в .Net

Если вы пытаетесь ссылаться на стиль Android, вам нужно поставить «android:» там

android:theme="@android:style/Theme.Black"

. Если это не решит его, вам может потребоваться изменить ваш вопрос с помощью полный файл манифеста, поэтому мы можем увидеть подробности

0
задан JNA 5 March 2019 в 18:51
поделиться

2 ответа

Решение станет немного сложнее, чем текущее, но больше не будет выделений строк. Работает для .NET Core 2.2

long machineId = 0;
long employeeId = 0;

var description = "machineId: 276744, engineId: 59440, employeeId: 4619825";

ReadOnlySpan<char> descriptionSpan = description.AsSpan();

var nameValueBlockStartIndex = 0;
while(nameValueBlockStartIndex < description.Length)
{
    var blockEndIndex = description.IndexOf(',', nameValueBlockStartIndex);
    if (blockEndIndex == -1)
    {
        blockEndIndex = description.Length;
    }

    var namePartEndIndex = description.IndexOf(':', nameValueBlockStartIndex);
    var namePartLength = namePartEndIndex - nameValueBlockStartIndex;
    var namePart = descriptionSpan.Slice(nameValueBlockStartIndex, namePartLength);

    var valuePartStartIndex = namePartEndIndex + 1;
    var valuePartLength = blockEndIndex - valuePartStartIndex + 1;
    var valuePart = descriptionSpan.Slice(valuePartStartIndex, valuePartLength - 1);

    while(namePart[0] == ' ')
    {
        namePart = namePart.Slice(1);
    }

    if (namePart.Equals("machineId", StringComparison.OrdinalIgnoreCase))
    {
        Int64.TryParse(valuePart, out machineId);
    }
    else if (namePart.Equals("employeeId", StringComparison.OrdinalIgnoreCase))
    {
        Int64.TryParse(valuePart, out employeeId);
    }

    nameValueBlockStartIndex = blockEndIndex + 1;
}
0
ответ дан khoroshevj 5 March 2019 в 18:51
поделиться

Это решение работает с .NET Core 2.2. Он использует метод расширения без выделения на ReadOnlySpan<char> (SplitNext).

public class Program {
    public void MyAnswer() {
        long machineId = 0;
        long employeeId = 0;

        var description = "machineId: 276744, engineId: 59440, employeeId: 4619825";

        var span = description.AsSpan();
        while (span.Length > 0) {
            var entry = span.SplitNext(',');

            var key = entry.SplitNext(':').TrimStart(' ');
            var value = entry.TrimStart(' ');

            if (key.Equals("machineId", StringComparison.Ordinal)) {
                long.TryParse(value, out machineId);
            }
            if (key.Equals("employeeId", StringComparison.Ordinal)) {
                long.TryParse(value, out employeeId);
            }
        }
    }
}

public static class Extensions {
    public static ReadOnlySpan<char> SplitNext(this ref ReadOnlySpan<char> span, char seperator) {
        int pos = span.IndexOf(seperator);
        if (pos > -1) {
            var part = span.Slice(0, pos);
            span = span.Slice(pos + 1);
            return part;
        } else {
            var part = span;
            span = span.Slice(span.Length);
            return part;
        }
    }
}

Я сравнил ваш исходный код, существующий ответ и мой ответ через BenchmarkDotnet. Это показывает, что это решение действительно без выделения ресурсов и работает быстрее, чем оригинальная версия:

BenchmarkDotNet=v0.11.4, OS=Windows 10.0.17763.316 (1809/October2018Update/Redstone5)
Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=2.2.104
  [Host]     : .NET Core 2.2.2 (CoreCLR 4.6.27317.07, CoreFX 4.6.27318.02), 64bit RyuJIT
  DefaultJob : .NET Core 2.2.2 (CoreCLR 4.6.27317.07, CoreFX 4.6.27318.02), 64bit RyuJIT

|   Method |       Mean |     Error |    StdDev | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
|--------- |-----------:|----------:|----------:|------------:|------------:|------------:|--------------------:|
| Original | 1,164.1 ns | 11.606 ns | 10.289 ns |      0.2937 |           - |           - |               928 B |
|   Answer |   460.5 ns |  4.527 ns |  4.234 ns |           - |           - |           - |                   - |
| MyAnswer |   445.7 ns |  2.578 ns |  2.412 ns |           - |           - |           - |                   - |

Помимо оптимизации обработки строк, фактическая функция синтаксического анализа также может быть оптимизирована. Это будет более быстрый анализатор длинных строк:

    public static long LongParseFast(ReadOnlySpan<char> value) {
        long result = 0;
        for (int i = 0; i < value.Length; i++) {
            result = 10 * result + (value[i] - 48);
        }
        return result;
    }

Если использовать его в моем примере, он удваивает производительность до 216.0 ns в моих тестах. Конечно, эта функция не может иметь дело с такими вещами, как отрицательные числа, запятые, точки и другие локали. Но если вы в порядке с этим, это, вероятно, так быстро, как вы можете.

0
ответ дан chrisn 5 March 2019 в 18:51
поделиться
Другие вопросы по тегам:

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