Лучший способ перевернуть строку

билинейная интерполяция просто означает взвешивание значения, основанного на 4 ближайших пикселях, к тому, которое вы изучаете. Весы можно рассчитать следующим образом.

cv::Point2f current_pos; //assuming current_pos is where you are in the image

//bilinear interpolation
float dx = current_pos.x-(int)current_pos.x;
float dy = current_pos.y-(int)current_pos.y;

float weight_tl = (1.0 - dx) * (1.0 - dy);
float weight_tr = (dx)       * (1.0 - dy);
float weight_bl = (1.0 - dx) * (dy);
float weight_br = (dx)       * (dy);

Ваше окончательное значение рассчитывается как сумма продуктов каждого пикселя с его соответствующим весом

403
задан R. Martinho Fernandes 3 March 2013 в 22:18
поделиться

13 ответов

public static string Reverse( string s )
{
    char[] charArray = s.ToCharArray();
    Array.Reverse( charArray );
    return new string( charArray );
}
533
ответ дан Ofer Zelig 3 March 2013 в 22:18
поделиться

"Лучший путь" зависит от того, что более важно для Вас в Вашей ситуации, производительности, элегантность, пригодность для обслуживания и т.д.

Так или иначе, вот подход с помощью Массива. Реверс:

string inputString="The quick brown fox jumps over the lazy dog.";
char[] charArray = inputString.ToCharArray(); 
Array.Reverse(charArray); 

string reversed = new string(charArray);
2
ответ дан Ash 3 March 2013 в 22:18
поделиться

Если строка будет содержать данные Unicode (строго говоря, non-BMP символы) другие методы, которые были отправлены, то повредит его, потому что Вы не можете подкачать порядок высоких и низких суррогатных элементов кода при инвертировании строки. (Больше информации об этом может быть найдено на мой блог .)

следующий пример кода правильно инвертирует строку, которая содержит non-BMP символы, например, "\U00010380\U00010381" (угаритская Буква Alpa, угаритская Бета Буквы).

public static string Reverse(this string input)
{
    if (input == null)
        throw new ArgumentNullException("input");

    // allocate a buffer to hold the output
    char[] output = new char[input.Length];
    for (int outputIndex = 0, inputIndex = input.Length - 1; outputIndex < input.Length; outputIndex++, inputIndex--)
    {
        // check for surrogate pair
        if (input[inputIndex] >= 0xDC00 && input[inputIndex] <= 0xDFFF &&
            inputIndex > 0 && input[inputIndex - 1] >= 0xD800 && input[inputIndex - 1] <= 0xDBFF)
        {
            // preserve the order of the surrogate pair code units
            output[outputIndex + 1] = input[inputIndex];
            output[outputIndex] = input[inputIndex - 1];
            outputIndex++;
            inputIndex--;
        }
        else
        {
            output[outputIndex] = input[inputIndex];
        }
    }

    return new string(output);
}
49
ответ дан Bradley Grainger 3 March 2013 в 22:18
поделиться
  • 1
    @LazyOne, хм что относительно флага END как hakre упомянутый выше? – Pacerier 12 October 2012 в 20:55

Это оказывается удивительно хитрым вопросом.

я рекомендовал бы использовать Массив. Реверс для большинства случаев, поскольку это кодируется исходно и очень просто поддержать и понять.

Это, кажется, превосходит StringBuilder по характеристикам во всех случаях, которые я протестировал.

public string Reverse(string text)
{
   if (text == null) return null;

   // this was posted by petebob as well 
   char[] array = text.ToCharArray();
   Array.Reverse(array);
   return new String(array);
}

существует второй подход, который может быть быстрее для определенных длин строки который Xor использования.

    public static string ReverseXor(string s)
    {
        if (s == null) return null;
        char[] charArray = s.ToCharArray();
        int len = s.Length - 1;

        for (int i = 0; i < len; i++, len--)
        {
            charArray[i] ^= charArray[len];
            charArray[len] ^= charArray[i];
            charArray[i] ^= charArray[len];
        }

        return new string(charArray);
    }

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

Вот сравнение производительности StringBuilder, Массива. Reverse и метод Xor.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ConsoleApplication4
{
    class Program
    {
        delegate string StringDelegate(string s);

        static void Benchmark(string description, StringDelegate d, int times, string text)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int j = 0; j < times; j++)
            {
                d(text);
            }
            sw.Stop();
            Console.WriteLine("{0} Ticks {1} : called {2} times.", sw.ElapsedTicks, description, times);
        }

        public static string ReverseXor(string s)
        {
            char[] charArray = s.ToCharArray();
            int len = s.Length - 1;

            for (int i = 0; i < len; i++, len--)
            {
                charArray[i] ^= charArray[len];
                charArray[len] ^= charArray[i];
                charArray[i] ^= charArray[len];
            }

            return new string(charArray);
        }

        public static string ReverseSB(string text)
        {
            StringBuilder builder = new StringBuilder(text.Length);
            for (int i = text.Length - 1; i >= 0; i--)
            {
                builder.Append(text[i]);
            }
            return builder.ToString();
        }

        public static string ReverseArray(string text)
        {
            char[] array = text.ToCharArray();
            Array.Reverse(array);
            return (new string(array));
        }

        public static string StringOfLength(int length)
        {
            Random random = new Random();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                sb.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))));
            }
            return sb.ToString();
        }

        static void Main(string[] args)
        {

            int[] lengths = new int[] {1,10,15,25,50,75,100,1000,100000};

            foreach (int l in lengths)
            {
                int iterations = 10000;
                string text = StringOfLength(l);
                Benchmark(String.Format("String Builder (Length: {0})", l), ReverseSB, iterations, text);
                Benchmark(String.Format("Array.Reverse (Length: {0})", l), ReverseArray, iterations, text);
                Benchmark(String.Format("Xor (Length: {0})", l), ReverseXor, iterations, text);

                Console.WriteLine();    
            }

            Console.Read();
        }
    }
}

Вот результаты:

26251 Ticks String Builder (Length: 1) : called 10000 times.
33373 Ticks Array.Reverse (Length: 1) : called 10000 times.
20162 Ticks Xor (Length: 1) : called 10000 times.

51321 Ticks String Builder (Length: 10) : called 10000 times.
37105 Ticks Array.Reverse (Length: 10) : called 10000 times.
23974 Ticks Xor (Length: 10) : called 10000 times.

66570 Ticks String Builder (Length: 15) : called 10000 times.
26027 Ticks Array.Reverse (Length: 15) : called 10000 times.
24017 Ticks Xor (Length: 15) : called 10000 times.

101609 Ticks String Builder (Length: 25) : called 10000 times.
28472 Ticks Array.Reverse (Length: 25) : called 10000 times.
35355 Ticks Xor (Length: 25) : called 10000 times.

161601 Ticks String Builder (Length: 50) : called 10000 times.
35839 Ticks Array.Reverse (Length: 50) : called 10000 times.
51185 Ticks Xor (Length: 50) : called 10000 times.

230898 Ticks String Builder (Length: 75) : called 10000 times.
40628 Ticks Array.Reverse (Length: 75) : called 10000 times.
78906 Ticks Xor (Length: 75) : called 10000 times.

312017 Ticks String Builder (Length: 100) : called 10000 times.
52225 Ticks Array.Reverse (Length: 100) : called 10000 times.
110195 Ticks Xor (Length: 100) : called 10000 times.

2970691 Ticks String Builder (Length: 1000) : called 10000 times.
292094 Ticks Array.Reverse (Length: 1000) : called 10000 times.
846585 Ticks Xor (Length: 1000) : called 10000 times.

305564115 Ticks String Builder (Length: 100000) : called 10000 times.
74884495 Ticks Array.Reverse (Length: 100000) : called 10000 times.
125409674 Ticks Xor (Length: 100000) : called 10000 times.

кажется, что Xor может быть быстрее для коротких строк.

125
ответ дан 11 revs, 4 users 97% 3 March 2013 в 22:18
поделиться
  • 1
    @Joe Let' s имеют пример на основе Ваших правил: URL запроса /id/login_openid. Начальное повторение: URL разделяется к уровню каталога и = login_openid. Это будет соответствовать правилу № 2 (строка № 5). Перезапись происходит, и новый URL /id/login_openid.php, и перезапись переходит к следующему повторению. Повторение № 2 : URL разделяется вниз и = login_openid.php. Это не будет очень никакие правила КРОМЕ последнего, которое говорит Apache прерываться, запрос (отправьте 403 ответа) - именно так работают Ваши текущие правила. – LazyOne 23 July 2011 в 18:39

Если Вы хотите играть в действительно опасную игру, то это - безусловно самый быстрый путь существует (приблизительно в четыре раза быстрее, чем Array.Reverse метод). Это - оперативное обратное использование указатели.

Примечание, что я действительно не рекомендую это ни для какого использования, никогда ( взглянули здесь по некоторым причинам, почему Вы не должны использовать этот метод ), но просто интересно видеть, что это может быть сделано, и что строки не действительно неизменны, как только Вы включаете небезопасный код.

public static unsafe string Reverse(string text)
{
    if (string.IsNullOrEmpty(text))
    {
        return text;
    }

    fixed (char* pText = text)
    {
        char* pStart = pText;
        char* pEnd = pText + text.Length - 1;
        for (int i = text.Length / 2; i >= 0; i--)
        {
            char temp = *pStart;
            *pStart++ = *pEnd;
            *pEnd-- = temp;
        }

        return text;
    }
}
13
ответ дан Community 3 March 2013 в 22:18
поделиться

Попытайтесь использовать Массив. Реверс


public string Reverse(string str)
{
    char[] array = str.ToCharArray();
    Array.Reverse(array);
    return new string(array);
}
10
ответ дан Mike Two 3 March 2013 в 22:18
поделиться

Взгляните на статью в Википедии здесь . Они реализуют Строку. Инвертируйте дополнительный метод. Это позволяет Вам писать код как это:

string s = "olleh";
s.Reverse();

Они также используют комбинацию ToCharArray/Reverse, которую предлагают другие ответы на этот вопрос. Исходный код похож на это:

public static string Reverse(this string input)
{
    char[] chars = input.ToCharArray();
    Array.Reverse(chars);
    return new String(chars);
}
11
ответ дан Mike Thompson 3 March 2013 в 22:18
поделиться

Извините за длинное сообщение, но это могло бы быть интересно

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        public static string ReverseUsingArrayClass(string text)
        {
            char[] chars = text.ToCharArray();
            Array.Reverse(chars);
            return new string(chars);
        }

        public static string ReverseUsingCharacterBuffer(string text)
        {
            char[] charArray = new char[text.Length];
            int inputStrLength = text.Length - 1;
            for (int idx = 0; idx <= inputStrLength; idx++) 
            {
                charArray[idx] = text[inputStrLength - idx];                
            }
            return new string(charArray);
        }

        public static string ReverseUsingStringBuilder(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return text;
            }

            StringBuilder builder = new StringBuilder(text.Length);
            for (int i = text.Length - 1; i >= 0; i--)
            {
                builder.Append(text[i]);
            }

            return builder.ToString();
        }

        private static string ReverseUsingStack(string input)
        {
            Stack<char> resultStack = new Stack<char>();
            foreach (char c in input)
            {
                resultStack.Push(c);
            }

            StringBuilder sb = new StringBuilder();
            while (resultStack.Count > 0)
            {
                sb.Append(resultStack.Pop());
            }
            return sb.ToString();
        }

        public static string ReverseUsingXOR(string text)
        {
            char[] charArray = text.ToCharArray();
            int length = text.Length - 1;
            for (int i = 0; i < length; i++, length--)
            {
                charArray[i] ^= charArray[length];
                charArray[length] ^= charArray[i];
                charArray[i] ^= charArray[length];
            }

            return new string(charArray);
        }


        static void Main(string[] args)
        {
            string testString = string.Join(";", new string[] {
                new string('a', 100), 
                new string('b', 101), 
                new string('c', 102), 
                new string('d', 103),                                                                   
            });
            int cycleCount = 100000;

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingCharacterBuffer(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingCharacterBuffer: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingArrayClass(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingArrayClass: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingStringBuilder(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingStringBuilder: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingStack(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingStack: " + stopwatch.ElapsedMilliseconds + "ms");

            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < cycleCount; i++) 
            {
                ReverseUsingXOR(testString);
            }
            stopwatch.Stop();
            Console.WriteLine("ReverseUsingXOR: " + stopwatch.ElapsedMilliseconds + "ms");            
        }
    }
}

Результаты:

  • ReverseUsingCharacterBuffer: 346 мс
  • ReverseUsingArrayClass: 87 мс
  • ReverseUsingStringBuilder: 824 мс
  • ReverseUsingStack: 2 086 мс
  • ReverseUsingXOR: 319 мс
5
ответ дан aku 3 March 2013 в 22:18
поделиться
  • 1
    @NikiC, таким образом, это - действительно рекомендация, I' ll имеют в виду его, Спасибо! It' s трудно для оставления позади старых привычек. – aorcsik 30 January 2014 в 11:04

Во-первых Вы не должны звонить ToCharArray, поскольку строка может уже быть индексирована как массив символов, таким образом, это сохранит Вас выделение.

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

public string Reverse(string text)
{
    if (string.IsNullOrEmpty(text))
    {
        return text;
    }

    StringBuilder builder = new StringBuilder(text.Length);
    for (int i = text.Length - 1; i >= 0; i--)
    {
        builder.Append(text[i]);
    }

    return builder.ToString();
}

Редактирование: Данные о производительности

я протестировал эту функцию и функцию с помощью Array.Reverse со следующей простой программой, где Reverse1 одна функция, и Reverse2 другой:

static void Main(string[] args)
{
    var text = "abcdefghijklmnopqrstuvwxyz";

    // pre-jit
    text = Reverse1(text); 
    text = Reverse2(text);

    // test
    var timer1 = Stopwatch.StartNew();
    for (var i = 0; i < 10000000; i++)
    {
        text = Reverse1(text);
    }

    timer1.Stop();
    Console.WriteLine("First: {0}", timer1.ElapsedMilliseconds);

    var timer2 = Stopwatch.StartNew();
    for (var i = 0; i < 10000000; i++)
    {
        text = Reverse2(text);
    }

    timer2.Stop();
    Console.WriteLine("Second: {0}", timer2.ElapsedMilliseconds);

    Console.ReadLine();
}

оказывается, что для коротких строк Array.Reverse метод приблизительно вдвое более быстр, чем тот выше, и для более длинных строк различие является еще более явным. Таким образом, учитывая, что Array.Reverse метод и более прост и быстрее, я рекомендовал бы использовать это, а не этого. Я оставляю на виду этого здесь только, чтобы показать, что это не способ, которым необходимо сделать это (к моему большому удивлению!)

11
ответ дан Greg Beech 3 March 2013 в 22:18
поделиться
  • 1
    @NikiC, он только разрабатывает, или у Вас есть некоторая причина позади него? – aorcsik 29 January 2014 в 19:51

Должен был отправить рекурсивный пример:

private static string Reverse(string str)
{
    if (str.IsNullOrEmpty(str) || str.Length == 1)
        return str;
    else
        return str[str.Length - 1] + Reverse(str.Substring(0, str.Length - 1));
}
4
ответ дан Abel 3 March 2013 в 22:18
поделиться
  • 1
    К вашему сведению, " Шрифты, обеспеченные by" необходимо добавить вручную к app' s plist. Значение в массиве имя файла . Значение передало [UIFont fontWithName:], PostScript/имя шрифта. – Hari Karam Singh 20 February 2013 в 08:29

Так как мне нравятся несколько ответов - один для использования string.Create и поэтому высокая производительность и низкое выделение и другой для правильности - использование StringInfo класс, я решил, что объединенный подход необходим. Это - окончательный строковый метод реверсирования:)

private static string ReverseString(string str)
    {
        return string.Create(str.Length, str, (chars, state) =>
        {
            var enumerator = StringInfo.GetTextElementEnumerator(state);
            var position = state.Length;
            while (enumerator.MoveNext())
            {
                var cluster = ((string)enumerator.Current).AsSpan();
                cluster.CopyTo(chars.Slice(position - cluster.Length));
                position -= cluster.Length;
            }
        });
    }

существует еще лучший способ использовать метод класса StringInfo, который пропускает много строковых выделений Перечислителем путем возврата просто индексов.

private static string ReverseString(string str)
    {
        return string.Create(str.Length, str, (chars, state) =>
        {
            var position = 0;
            var indexes = StringInfo.ParseCombiningCharacters(state); // skips string creation
            var stateSpan = state.AsSpan();
            for (int len = indexes.Length, i = len - 1; i >= 0; i--)
            {
                var index = indexes[i];
                var spanLength = i == len - 1 ? state.Length - index : indexes[i + 1] - index;
                stateSpan.Slice(index, spanLength).CopyTo(chars.Slice(position));
                position += spanLength;
            }
        });
    }

Некоторые сравнительные тесты по сравнению с решением LINQ:

String length 20:

LINQ                       Mean: 2,355.5 ns   Allocated: 1440 B
string.Create              Mean:   851.0 ns   Allocated:  720 B
string.Create with indexes Mean:   466.4 ns   Allocated:  168 B

String length 450:

LINQ                          Mean: 34.33 us   Allocated: 22.98 KB
string.Create                 Mean:   19.13 us   Allocated: 14.98 KB
string.Create with indexes    Mean:   10.32 us   Allocated: 2.69 KB
1
ответ дан SET 29 August 2019 в 19:13
поделиться

Greg Beech опубликовал unsafe вариант, который действительно настолько быстр, насколько это возможно (это ин-плейс реверс); но, как он указал в своем ответе, это совершенно катастрофическая идея.

Тем не менее, я удивлен, что существует такой консенсус, что Array.Reverse является самым быстрым методом. Существует еще unsafe подход, который возвращает обратную копию строки (без махинаций с обращением на месте) значительно быстрее, чем Array.Reverse метод для небольших строк:

public static unsafe string Reverse(string text)
{
    int len = text.Length;

    // Why allocate a char[] array on the heap when you won't use it
    // outside of this method? Use the stack.
    char* reversed = stackalloc char[len];

    // Avoid bounds-checking performance penalties.
    fixed (char* str = text)
    {
        int i = 0;
        int j = i + len - 1;
        while (i < len)
        {
            reversed[i++] = str[j--];
        }
    }

    // Need to use this overload for the System.String constructor
    // as providing just the char* pointer could result in garbage
    // at the end of the string (no guarantee of null terminator).
    return new string(reversed, 0, len);
}

Вот некоторые эталонные результаты.

Видно, что прирост производительности уменьшается, а затем исчезает по сравнению с методом Array.Reverse по мере увеличения размера строк. Однако для строк малого и среднего размера этот метод трудно превзойти.

17
ответ дан 22 November 2019 в 23:26
поделиться
public string rev(string str)
{
    if (str.Length <= 0)
        return string.Empty;
    else
        return str[str.Length-1]+ rev(str.Substring(0,str.Length-1));
}
-4
ответ дан 22 November 2019 в 23:26
поделиться
Другие вопросы по тегам:

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