2015-10-02 12 views
0

В настоящее время я работаю над вызовом Codewars, http://www.codewars.com/kata/your-order-please. Задача состоит в том, чтобы взять строку и переупорядочить слова в соответствии со значением, найденным в каждом слове строки, например: «is2 Thi1s T4est 3a», функция должна вернуть «Thi1s is2 3a T4est».JavaScript while loop efficiency/performance

Я написал решение, которое успешно передает все предоставленные тесты и возвращает правильную строку. https://jsfiddle.net/louisstanard/5hygz6wb/

function order(words){ 
    var ordered = []; 
    var arr = words.split(' '); 
    var n = 1; 
    while (n <= arr.length) { 
    for (var i = 0; i < arr.length; i++) { 
     var stringArr = arr[i].split(''); 
     stringArr.forEach(function(currentValue, index) { 
     if (parseInt(currentValue) === n) { 
      ordered.push(arr[i]); 
      n++; 
     } 
     }); 
    } 
    } 
    return ordered.join(' '); 
} 

Моя проблема заключается в том, что, когда я пытаюсь представить решение, которое я получаю ошибку о том, «Процесс был прерван. Это заняло больше времени, чем 6000ms завершить». Я решил использовать цикл while, потому что я хочу продолжить итерацию над каждым словом в строке, которая ищет число, пока я не построил новый массив, длина которого совпадает с исходным массивом.

Я новичок в написании более опытных JS, но я знаю, что, хотя петли (и, вероятно, для вложенных внутри себя) могут быть очень дорогими операциями. Кто-нибудь знает, почему это может занять слишком много времени? Есть ли вопиющие проблемы с производительностью, которые я не вижу? Или, может быть, лучший подход? Благодаря!

+2

Это может быть лучше подходит для http://codereview.stackexchange.com/ – 1252748

+1

@thomas Я забыл о сообществе codereview - вы правы, это было бы лучше. В следующий раз я отправлю туда. Благодаря! –

ответ

0

Это еще один способ сделать это:

function order(words){ 
    return words 
    .split(' ') 
    .sort(function(wordA, wordB) { 
     var numA = +(wordA.match(/\d+/g)[0]); 
     var numB = +(wordB.match(/\d+/g)[0]); 
     return numA - numB; 
    }) 
    .join(' '); 
} 
+0

, предоставляющий другой способ сделать это, не отвечает на вопрос – charlietfl

+0

OP также спросил, есть ли: «возможно, лучший подход вообще?». Я дал один, который был ясен, лаконичен и не зацикливался дольше 6000 мс, что было его проблемой. – TbWill4321

+0

ОК ... достаточно справедливо ...только смотрел на причину. – charlietfl

0

Посмотрите на обновление для вашего Fiddle here. В моем браузере Chrome на порядок выше, чем у оригинала.

function orderNew(words){ 
    var ordered = []; 
    var arr = words.split(' '); 

    arr.forEach(function(item, index){ 
     var match = /\d+/.exec(item); 
     ordered[parseInt(match[0])] = item; 
    }); 
    return ordered.join(' '); 
} 
0

Ваш код работает медленно, потому что вы делаете много ненужных вычислений:

  • вы не кэшировать длину ваших двух массивов, так что на каждой итерации, вы проверить длину снова.
  • у вас есть 3 петли, где хватит одной петли.
  • вы проверяете каждую букву в словах, в то время как parseInt (слово, 10) уже возвращает первое число внутри слова, поэтому циклирование по буквам бесполезно.
  • Ваш цикл while и первый для цикла в основном делают то же самое, поскольку оба они начинаются с 0 и заканчиваются на количество слов, содержащихся в исходной строке.
  • вы подталкиваете результаты к массиву вместо того, чтобы просто устанавливать упорядоченные [i] = arr [i].
  • ваши петли не содержат перерывов, поэтому вы всегда продолжаете цикл, даже если вы уже нашли правильный результат (число в этом случае).
  • Логика попытки создания нового массива до тех пор, пока он не будет иметь длину исходного массива, является ошибочным, так как если вы закончите цикл, новый массив будет всегда иметь длину оригинала, если ваш код верен.

Таким образом, да, это будет более эффективным, чтобы использовать один из методов, который опубликовал другой ppl, поскольку этот код более оптимизирован и не содержит избыточной логики.

+0

Спасибо за углубленное разбиение @Shilly! Очень признателен. –