regex как захватить и заменить каждое появление n-го символа [duplicate]

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

2
задан Cat Overlord 16 August 2015 в 00:32
поделиться

7 ответов

Чтобы поддерживать повторное использование и возможность обернуть это в объект / функцию, давайте его параметризуем:

var str = "abcdefoihewfojias".split('');
var nth = 4; // the nth character you want to replace
var replaceWith = "|" // the character you want to replace the nth value
for (var i = nth-1; i < str.length-1; i+=nth) {
    str[i] = replaceWith;
}
alert( str.join("") );
2
ответ дан user2723025 18 August 2018 в 05:57
поделиться
  • 1
    Если вы собираетесь использовать более старые методы. Вы хотите использовать charAt – Downgoat 16 August 2015 в 01:15

Хотя уже есть несколько ответов, я подумал, что предлагаю немного альтернативный подход, используя Array.prototype.map(), завернутый в функцию, которая может быть адаптирована пользователем (для обновления значения n в символе nth и измените используемый символ замены):

// defining the named function, with an 'opts' argument:
function replaceNthWith(opts) {

  // setting the default options:
  var defaults = {

    // defining the nth character, in this case
    // every fourth:
    'nth': 4,

    // defining the character to replace that
    // nth character with:
    'char': '|'
  };

  // Note that there's no default string argument,
  // so that one argument must be provided in the
  // opts object.

  // iterating over each property in the
  // opts Object:
  for (var property in opts) {

    // if the current property is a property of
    // this Object, not inherited from the Object 
    // prototype:
    if (opts.hasOwnProperty(property)) {

      // we set that property of the defaults
      // Object to be equal to that property
      // as set in the opts Object:
      defaults[property] = opts[property];
    }
  }

  // if there is a defaults.string property
  // (inherited from the opts.string property)
  // then we go ahead; otherwise nothing happens
  // note: this property must be set for the
  // function to do anything useful:
  if (defaults.string) {

    // here we split the string supplied from the user,
    // via opts.string, in defaults.string to form an
    // Array of characters; we iterate over that Array
    // with Array.prototype.map(), which process one
    // Array and returns a new Array according to the
    // anonymous function supplied:
    return haystack = defaults.string.split('').map(function(character, index) {

      // here, when the index of the current letter in the
      // Array formed by Array.prototype.split() plus 1
      // (JavaScript is zero-based) divided by the number
      // held in defaults.nth is equal to zero - ensuring
      // that the current letter is the 'nth' index we return
      // the defaults.char character; otherwise we return
      // the original character from the Array over which
      // we're iterating:
      return (index + 1) % parseInt(defaults.nth) === 0 ? defaults.char : character;

    // here we join the Array back into a String, using
    // Array.prototype.join() with an empty string:
    }).join('');
  }

}

// 'snippet.log()' is used only in this demonstration, in real life use
// 'console.log()', or print to screen or display in whatever other
// method you prefer:
snippet.log( replaceNthWith({ 'string': "abcdefoihewfojias" }) );

function replaceNthWith(opts) {
  var defaults = {
    'nth': 4,
    'char': '|'
  };

  for (var property in opts) {
    if (opts.hasOwnProperty(property)) {
      defaults[property] = opts[property];
    }
  }

  if (defaults.string) {
    return haystack = defaults.string.split('').map(function(character, index) {

      return (index + 1) % parseInt(defaults.nth) === 0 ? defaults.char : character;

    }).join('');
  }

}

// 'snippet.log()' is used only in this demonstration, in real life use
// 'console.log()', or print to screen or display in whatever other
// method you prefer.

// calling the function, passing in the supplied 'string'
// property value:
snippet.log( replaceNthWith({
    'string': "abcdefoihewfojias"
}) );
// outputs: abc|efo|hew|oji|s

// calling the function with the same string, but to replace
// every second character ( 'nth' : 2 ):
snippet.log( replaceNthWith({
    'string': "abcdefoihewfojias",
    'nth': 2
}) );
// outputs: a|c|e|o|h|w|o|i|s

// passing in the same string once again, working on every
// third character, and replacing with a caret ('^'):
snippet.log( replaceNthWith({
    'string': "abcdefoihewfojias",
    'nth': 3,
    'char' : '^'
}) );
// outputs: ab^de^oi^ew^oj^as
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Ссылки:

0
ответ дан David Thomas 18 August 2018 в 05:57
поделиться

.map one-liner

Вы можете использовать этот однострочный:

var str = "abcdefoihewfojias";
str.split('').map(function(l,i) {
    return (i + 1) % 4 ? l : '|';
}).join('');

% возвращает остаток. Итак:

 # | Result (# + 1) % 4
---|-------
 0 | 1
 1 | 2
 2 | 3
 4 | 0 // Bingo!

Альтернатива ES6

С ES6 вы можете сделать:

[...str].map((l,i) => (i + 1) % 4 ? l : '|')
2
ответ дан Downgoat 18 August 2018 в 05:57
поделиться
  • 1
    Согласовано, но вам нужно объяснить свой ответ, чтобы OP - и любые будущие пользователи - могли понять , почему это работает. – David Thomas 16 August 2015 в 00:43

Вы могли бы просто сделать это с заменой регулярного выражения:

var str = "abcdefoihewfojias";
    
var result = str.replace(/(...)./g, "$1|");

console.log(result);

4
ответ дан James Montagne 18 August 2018 в 05:57
поделиться
  • 1
    Возможно, я слишком скоро комментирую, но вы должны объяснить, как работает замена, и что означает регулярное выражение, чтобы завершить ответ, чтобы OP - и будущие пользователи - понимали , как он работает, и < я> почему . – David Thomas 16 August 2015 в 00:45
  • 2
    – FreeLightman 13 February 2016 в 08:36

Простой пример использования модуля

https://jsfiddle.net/ctfsorwg/

var str = "abcdefoihewfojias";
var outputStr = str.split("");
for (var i = 0; i < outputStr.length; i++) {
    if(!((i+1)%4))outputStr[i] = '|';
}
alert( "Before: " + str + "\nAfter: " + outputStr.join(""));
0
ответ дан SadiRubaiyet 18 August 2018 в 05:57
поделиться
2
ответ дан Downgoat 6 September 2018 в 19:54
поделиться
2
ответ дан Downgoat 30 October 2018 в 01:23
поделиться
Другие вопросы по тегам:

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