Эффективное манипулирование строками в Javascript - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть строка (содержимое HTML) и массив объектов позиции (индекса). Длина строки составляет около 1,6 миллиона символов и около 700 объектов позиции.

е:

var content = "<html><body><div class="c1">this is some text</div>...."
var positions = [{start: 20, end: 25}, {start: 35, end: 37}....]

Мне нужно вставить открывающий тег span в каждую начальную позицию в строке и закрывающий тег span в каждую конечную позицию в строке.

Какой самый эффективный способ сделать это?

До сих пор я пытался отсортировать массив позиций в обратном порядке, затем циклически проходить и затем использовать replace / splice для вставки тегов, например:

content = content.slice(0, endPosition) + "</span>" + content.substring(endPosition);
content = content.slice(0, startPosition) + "<span>" + content.slice(startPosition);

(Обратите внимание, как я начал цикл с конца, чтобы не перепутать начальную / конечную позиции).

Но это занимает около 3 секунд, что мне кажется медленным и неэффективным.

Какой более эффективный способ сделать это?

Ответы [ 4 ]

0 голосов
/ 13 ноября 2018

Вы можете сделать это:

const content = 'this is some text. this is some text. this is some text. this is some text. this is some text. this is some text. this is some text. this is some text. ';
const positions = [{start: 20, end: 26}, {start: 35, end: 37}];

// using Set will help in reducing duplicate position elements.
let starts = new Set();
let ends = new Set();

const START_TAG = '<span>';
const END_TAG = '</span>';

const string_length = content.length;

positions.forEach(function(position) {
   let _start = position.start;
   let _end = position.end;

   // check whether index positions are in-bound.
   if(_start > -1 && _start < string_length) starts.add(_start);
   if(_end > -1 && _end < string_length) ends.add(_end);
});

updated_string = content;

starts.forEach(function(position) {
  updated_string = updated_string.substr(0, position) + START_TAG + updated_string.substr(position);
});

ends.forEach(function(position) {
  updated_string = updated_string.substr(0, position) + END_TAG + updated_string.substr(position);
});

console.log(updated_string);
0 голосов
/ 13 ноября 2018

Мы можем разделить content на символы в массив, чем один цикл для вставки <span> </span>, а затем join обратно в строку

var content = '<html><body><div class="c1">this is some text</div>....';
var positions = [{start: 20, end: 25}, {start: 35, end: 37}];
var arr = content.split('');

var arrPositions = {
  starts: positions.map(_ => _.start),
  ends: positions.map(_ => _.end)
}

var result = arr.map((char, i) => {
  if (arrPositions.starts.indexOf(i) > -1) {
    return '<span>' + char;
  }
  if (arrPositions.ends.indexOf(i) > -1) {
    return '</span>' + char;
  }
  return char
}).join('')

console.log(result)
0 голосов
/ 13 ноября 2018

Вы можете сделать:

const content = '<div class="c1">It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using Content here, content here, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for lorem ipsum will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).</div>';
const positions = [{start: 24,end: 40}, {start: 160,end: 202}];
const result = positions
  .reduce((a, c, i, loopArray) => {
    a.array.push(
      content.slice(a.lastPosition, c.start), '<span class="blue">', content.slice(c.start, c.end), '</span>'
    );
    
    a.lastPosition = c.end;
    
    if (loopArray.length === ++i) {
      a.array.push(content.slice(a.lastPosition));
    }
    
    return a;
  }, {array: [], lastPosition: 0})
  .array
  .join('');

document.write(result);
.blue {color: blue;}
0 голосов
/ 13 ноября 2018

Вместо того, чтобы каждый раз модифицировать большую строку, попробуйте накапливать обработанные «куски» в новый буфер:

content = '0123456789'
positions = [
  [1, 3],
  [5, 7]
]

buf = []
lastPos = 0

for (let [s, e] of positions) {
  buf.push(
    content.slice(lastPos, s),
    '<SPAN>',
    content.slice(s, e),
    '</SPAN>'
  )
  lastPos = e
}

buf.push(content.slice(lastPos))


res = buf.join('')
console.log(res)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...