2015-03-10 5 views
1

Эта функция перебирает JavaScript вложенных массивов (рекурсивно) и заменяет строки внутри них: примерJavaScript: Аргументы с более чем одним значением

function replaceRecur(tree, str, newStr) { 
    for (var i = 1; i < tree.length; i++) { 
    if (Array.isArray(tree[i])) { 
     replaceRecur(tree[i], str, newStr) 
    } else { 
     tree[i] = tree[i].replace(str, newStr) 
    } 
    } 
} 

Использование:

function replaceQuotes(tree, callback) { 
    var str1 = /"(?=\b)/g 
    , str2 = /"(?!\b)/g 
    , newStr1 = '“' 
    , newStr2 = '”' 

    replaceRecur(tree, str1, newStr1) 
    replaceRecur(tree, str2, newStr2) 

    callback(null, tree) 
} 

Как я должен изменить replaceRecur поэтому я допускаю два значения для аргумента?

Пример:

function replaceQuotes(tree, callback) { 
    var str = ['/"(?=\b)/g/', '"(?!\b)/g'] 
    , newStr = '“ ”' // not sure whether to use arrays or strings 
        // what's more common? 

    replaceRecur(tree, str, newStr) 

    callback(null, tree) 
} 

(.. Причина в том, я не хочу повторять replaceRecur, str и newStr дважды я хочу, чтобы сохранить код DRY)

EDIT:

Пример ввода (на всякий случай):

[ 'markdown', 
    [ 'para', '“a paragraph”' ], 
    [ 'hr' ], 
    [ 'para', '\'another paragraph\'' ], 
    [ 'para', 'test--test' ], 
    [ 'para', 'test---test' ], 
    [ 'bulletlist', 
    [ 'listitem', '“a list item”' ], 
    [ 'listitem', '“another list item”' ] ] ] 
+2

Я думаю, что ваш код уже сух. Вы не повторяетесь, вы вызываете функцию несколько раз с разными аргументами? Если вообще использовать цикл в 'replaceQuotes'. – Bergi

+1

Я с @Bergi, просто вызов функции дважды не означает, что вы повторяете себя. И добавление сложности к простой функции, чтобы избежать этого, не обязательно является хорошей идеей. –

+0

@ Bergi Не могли бы вы привести пример? – alexchenco

ответ

3

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

function traverse(tree, callback) { 
    for (var i = 0; i < tree.length; ++i) { 
    if (Array.isArray(tree[i])) 
     traverse(tree[i], callback); 
    else 
     tree[i] = callback(tree[i]); 
    } 
} 

function replaceTwo(tree, s1from, s1to, s2from, s2to) { 
    traverse(tree, function(element) { 
    return element.replace(s1from, s1to).replace(s2from, s2to); 
    }); 
} 

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

+0

plus1 - 'traverse' гораздо полезнее, чем' replaceRecur', который идет глубоко. –

0

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


Но на ваш вопрос: Вы можете просто добавить два аргумента функции, игнорируя их, если не дано:

function replaceRecur(tree, str1, newStr1, str2, newStr2) { 
    for (var i = 1; i < tree.length; i++) { 
    if (Array.isArray(tree[i])) { 
     replaceRecur(tree[i], str1, newStr1, str2, newStr2); 
    } else { 
     tree[i] = tree[i].replace(str1, newStr1); 
     if (typeof str2 !== "undefined") { 
     tree[i] = tree[i].replace(str2, newStr2); 
     } 
    } 
    } 
} 

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

function replaceRecur(tree, str, newStr/*, str2, newStr2, ...*/) { 
    for (var i = 1; i < tree.length; i++) { 
    if (Array.isArray(tree[i])) { 
     replaceRecur.apply(this, arguments); 
    } else { 
     for (var arg = 1; arg + 1 < arguments.length; arg += 2) { 
     tree[i] = tree[i].replace(arguments[arg], arguments[arg + 1]); 
     } 
    } 
    } 
} 

Обратите внимание, что на некоторых системах, использующих JavaScript arguments псевдо-массив оказывает негативное влияние на производительность. На современных двигателях это вообще не имеет значения.

Использование:

replaceRecur(tree, /"(?=\b)/g, '“', /"(?!\b)/g, '”'); 
0

просто изменить else применять каждый регулярное выражение в массиве.

else { 
    //array is the array of regex's passed 
    array.forEach(function(item) { 
     tree[i] = tree[i].replace(item, newStr); 
    }); 
} 
+0

Возможно, вы могли бы каким-то образом поставить это в контексте, так как это довольно непонятно и заменяет ** все ** «исходных» строк на полную целевую строку. Если это подразумевается, чтобы следовать от частичной попытки OP, он не может этого сделать. –

+0

Его не следует, его псевдокод и шаг в правильном направлении –

1

не уверен, следует ли использовать массивы или строки

Используйте массивы, вы можете заменить несколько вещей. И вы не измените replaceRecur, это нормально, как есть.Скорее ввести новую функцию

function replaceMultipleRecur(tree, strArr, newStrArr) { 
    … // (in the simplest occasion a loop over the arrays with calls to replaceRecur) 
} 
function replaceQuotes(tree) { 
    return replaceMultipeRecur([/"(?=\b)/g, /"(?!\b)/g], ['“', '”']); 
} 

Я не хочу повторять replaceRecur, ул и NewStr дважды

Вы можете просто использовать функцию exsting, пропусканием регулярное выражение, которое соответствует всем вашим случаев и replacer callback вместо строк.

function replaceQuotes(tree) { 
    replaceRecur(tree, /("\b)|("\B)/g, function(m, l, r) { 
     return l ? '“' : '”'; 
    }); 
    return tree 
} 
Смежные вопросы