Как получить нечетные и четные символы позиции из строки? - PullRequest
1 голос
/ 24 марта 2019

Я пытаюсь выяснить, как удалить каждый второй символ (начиная с первого) из строки в Javascript. Например, строка «Это тест!» должен стать "hsi etTi sats!" Я также хочу сохранить каждый удаленный символ в другой массив.

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

function encrypt(text, n) {
  if (text === "NULL") return n;
  if (n <= 0) return text;
  var encArr = [];
  var newString = text.split("");
  var j = 0;
  for (var i = 0; i < text.length; i += 2) {
    encArr[j++] = text[i];
    newString.splice(i, 1); // this line doesn't work properly
  }
}

Ответы [ 9 ]

2 голосов
/ 25 марта 2019

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

function encrypt(string) {
    var array = [...string],
        i = 0,
        l = array.length >> 1;
    
    while (i <= l) array.push(array.splice(i++, 1)[0]);
    
    return array.join('');
}

console.log(encrypt("This is a test!"));
2 голосов
/ 24 марта 2019

Вы можете reduce символов строки и сгруппировать их в отдельные массивы, используя оператор %. Используйте destructuring , чтобы вернуть 2D-массив в отдельные переменные

let str = "This is a test!";

const [even, odd] = [...str].reduce((r,char,i) => (r[i%2].push(char), r), [[],[]])

console.log(odd.join(''))
console.log(even.join(''))

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

let str = "This is a test!",
    odd = [],
    even = [];

for (var i = 0; i < str.length; i++) {
  i % 2 === 0
    ? even.push(str[i]) 
    : odd.push(str[i])
}

console.log(odd.join(''))
console.log(even.join(''))
2 голосов
/ 24 марта 2019

Вероятно, было бы проще использовать регулярное выражение и .replace: захватить два символа в отдельных группах захвата, добавить первый символ в строку и заменить вторым символом. Затем вы получите первую половину нужного вам вывода в одной строке, а вторую - в другой: просто объедините их вместе и верните:

function encrypt(text) {
  let removedText = '';
  const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => {
    // in case the match was at the end of the string,
    // and the string has an odd number of characters:
    if (!secondChar) secondChar = '';
    // remove the firstChar from the string, while adding it to removedText:
    removedText += firstChar;
    return secondChar;
  });
  return replacedText1 + removedText;
}
console.log(encrypt('This is a test!'));
1 голос
/ 26 марта 2019

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

function test(func, n){
	var text = "";
	for(var i = 0; i < n; ++i){
		text += "a";
    }	
	var start = new Date().getTime();
	func(text);
	var end = new Date().getTime();
  var time =  (end-start) / 1000.0;
	console.log(func.name, " took ", time, " seconds")
  return time;
}

function encryptREGEX(text) {
  let removedText = '';
  const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => {
    // in case the match was at the end of the string,
    // and the string has an odd number of characters:
    if (!secondChar) secondChar = '';
    // remove the firstChar from the string, while adding it to removedText:
    removedText += firstChar;
    return secondChar;
  });
  return replacedText1 + removedText;
}

function encrypt(text) {
  text = text.split("");
  var removed = "";
  var encrypted = text.filter((letter, index) => {
    if(index % 2 == 0){
      removed += letter;
      return false;
    }
    return true
  }).join("")
  return encrypted + removed
}

var timeREGEX = test(encryptREGEX, 10000000);
var timeFilter = test(encrypt, 10000000);

console.log("Using filter is faster ", timeREGEX/timeFilter, " times")

filter vs regex - performance test result

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

1 голос
/ 25 марта 2019

Может быть с разделением, фильтрацией и объединением:

const remaining = myString.split('').filter((char, i) => i % 2 !== 0).join('');
const deleted = myString.split('').filter((char, i) => i % 2 === 0).join('');

1 голос
/ 24 марта 2019

как это?

var text = "This is a test!"
var result = ""
var rest = ""
for(var i = 0; i < text.length; i++){
        if( (i%2) != 0 ){
          result += text[i]
	} else{
	  rest += text[i]
        }
}
console.log(result+rest)
1 голос
/ 24 марта 2019

Я думаю, вы были на правильном пути.То, что вы пропустили, это замена, используя либо строку, либо RegExp.

Метод replace () возвращает новую строку с некоторыми или всеми совпадениями шаблона, замененными заменой.Шаблон может быть строкой или RegExp, а замена может быть строкой или функцией, вызываемой для каждого совпадения.Если шаблон является строкой, будет заменено только первое вхождение.

Источник: String.prototype.replace ()

Если вызаменяя значение (а не регулярное выражение), будет заменен только первый экземпляр значения.Чтобы заменить все вхождения указанного значения, используйте глобальный модификатор (g)

Источник: JavaScript String replace () Метод

Поэтому мое предложение будетчтобы продолжить с заменой и передать правильный RegExp в функцию, я думаю, вы можете понять из этого примера - это удаляет каждое второе вхождение для char 't':

let count = 0;
let testString = 'test test test test';

console.log('original', testString);

// global modifier in RegExp
let result = testString.replace(/t/g, function (match) {
  count++;
  return (count % 2 === 0) ? '' : match;
});

console.log('removed', result);
1 голос
/ 24 марта 2019

Довольно просто с помощью .reduce() создать два массива, которые вам нужны.

function encrypt(text) {
  return text.split("")
             .reduce(({odd, even}, c, i) => 
                i % 2 ? {odd: [...odd, c], even} : {odd, even: [...even, c]}
             , {odd: [], even: []})
}

console.log(encrypt("This is a test!"));

Их можно преобразовать в строки, используя .join(""), если хотите.

1 голос
/ 24 марта 2019

function encrypt(text) {
  text = text.split("");
  var removed = []
  var encrypted = text.filter((letter, index) => {
    if(index % 2 == 0){
      removed.push(letter)
      return false;
    }
    return true
  }).join("")
  return {
      full: encrypted + removed.join(""),
      encrypted: encrypted,
      removed: removed
  }
}

console.log(encrypt("This is a test!"))

Splice не работает, потому что если вы удаляете элемент из массива в for loop индексах, скорее всего, будет неправильно при удалении другого элемента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...