Регулярное выражение для поиска пар в массиве

Я хотел бы разобрать эту строку:

[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]

Чтобы иметь значение ключа (JSON)

{
"abc.d.2": "mcnv.3.we",
"abec.d.2: "mcnv.4.we",
"abhc.d.2": "mcnv.5.we"
}

Сначала я хотел бы проверить, можно ли проанализировать строку, чтобы сделать ее ключ => значение. Как я могу проверить строку, если она содержит пары?

Спасибо

Я пробовал это: ([. *?,. *?]) Но пары недостаточно :( Кстати: я никогда не задаю вопрос, если я не пробовал несколько часов назад

IsraGab 24.07.2018 17:18

Ожидаете ли вы большего количества уровней вложенности?

Paolo 24.07.2018 17:19

@UnbearableLightness нет

IsraGab 24.07.2018 17:19

@UnbearableLightness Тогда вам стоит поделиться своими усилиями, о которых идет речь. Также в отношении .* в нем будет учитываться даже запятая. Попытайтесь быть более конкретным

Rajesh 24.07.2018 17:20

@IsraGab ты что-то вроде \[\[([^,]+),([^\]]+)],\[([^,]+),([^\]]+)],\[([^,]+),([^\]]+)‌​\]\]? Попробуйте здесь. Заменить на {\n"\1": "\2",\n"\3": "\4",\n"\5": "\6",\n}

Paolo 24.07.2018 18:17

Нет: я обновил регулярное выражение, которое вы отправили, фактической строкой, которую мне нужно проанализировать. Строка, которую я публикую здесь, является примером, но реальная строка намного больше, чем эта: regex101.com/r/GReD6H/2

IsraGab 24.07.2018 18:20

Тогда вам понадобится цикл, поскольку рекурсия не поддерживается в регулярном выражении Javascript.

Paolo 24.07.2018 18:21

По какой причине вы конкретно используете регулярное выражение? Не можете ли вы проанализировать его как двумерный массив и использовать javascript для проверки дубликатов? [["abc.d.2", "mcnv.3.we"], ["abec.d.2", "mcnv.4.we"], ["abhc.d.2", "mcnv.5.we"]]

Arye Eidelman 24.07.2018 18:35

@ Arye Dov Eidelman, строка поступает из уведомления веб-сокета, я не знаю, как будут выглядеть данные в сокете, поэтому я хотел бы проверить, какое регулярное выражение соответствует строке, чтобы отправить ее в нужную функцию

IsraGab 25.07.2018 21:03
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
9
161
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Вы можете попробовать что-то вроде этого:

Подход 1:

Идея:

  • Обновите регулярное выражение, чтобы в нем были более конкретные символы. В вашем случае буквенно-цифровые и точка.
  • Получить все совпадающие элементы из строки.
  • Все нечетные значения являются ключами, а четные совпадения - значениями.
  • Переберите спички и создайте объект.

const str = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]";
const matches = str.match(/[\w\.\d]+/gi);

const output = {};

for(var i = 0; i< matches.length; i+=2) {
  output[matches[i]] = matches[i+1];
}

console.info(output)

Подход 2:

Идея:

  • Напишите регулярное выражение для захвата каждой отдельной группы: [...:...]
  • Затем удалите скобки [ и ].
  • Разделите строку запятой ,.
  • Первая часть - ваш ключ. Во-вторых, ваша ценность.

const str = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]";
const matches = str.match(/\[([\w\d\.,]*)\]/gi);
const output = matches.reduce((obj, match) => {
  const parts = match.substring(1, match.length - 1).split(',');
  obj[parts[0]] = parts[1];
  return obj;
}, {})

console.info(output)

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

const str = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]";
const matches = str.match(/\[([\w\d\.,]*)\]/gi);
const output = matches.reduce((obj, match) => {
  const parts = match.substring(1, match.length - 1).split(',');
  obj.set(...parts)
  return obj;
}, new Map())

for (const [k, v] of output.entries()) {
  console.info(`Key: ${k}, value: ${v}`)
}

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

IsraGab 24.07.2018 17:29

@IsraGab, ты тоже можешь это сделать. Но для этого потребуется больше профессии. У вас может быть регулярное выражение для сопоставления текста между [], а затем разбить его с помощью строки. Если хочешь, могу завтра добавить отрывок.

Rajesh 24.07.2018 17:33

@ Раджеш, да, пожалуйста. Меня не волнует профессия, но, возможно, в следующий раз у меня будет по 3 элемента в каждом подмассиве, тогда я отправлю строку в функцию сопоставления для создания объекта. В текущем решении 2 жестко запрограммирован, он должен быть параметром в вызове функции

IsraGab 24.07.2018 17:37

У меня также есть еще одна проблема с вашим регулярным выражением. Он не проверяет [[]], поэтому я могу иметь простую строку, которая также будет соответствовать: abc.d.2, mcnv.3.we, [abec.d.2, mcnv.4.we, abhc.d. 2, mcnv.5.‌ мы

IsraGab 24.07.2018 17:40
Класс символов \w включает \d
Sunny Patel 24.07.2018 17:56

@IsraGab Я обновил свой ответ обсуждаемым подходом. Надеюсь, поможет!

Rajesh 26.07.2018 08:20

Разберите массив как JSON, перебирайте массив, добавляя записи к целевому объекту по ходу дела, следите за дублирующимися ключами:

let dict_target = {}; // The target dictionary, 
let src, arysrc, proceed = false;

try {
    src = "[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]"
                  .replace(/,/g, '","')
                  .replace(/\]","\[/g, '"],["')
                  .replace(/^\[\[/, '[["')
                  .replace(/\]\]$/, '"]]')
             ;
    arysrc = JSON.parse(src);
    proceed = true; // Could parse the data, can carry on with processing the data
} catch (e) {
    console.info(`Source data unparseable, error '${e.message}'.`);
} 

if (proceed) {
    arysrc.forEach ( (a_item, n_idx) => {
        if (dict_target.hasOwnProperty(a_item[0])) {
           // add any tests and processing for duplicate keys/value pairs here  
           if (typeof dict_target[a_item[0]] === "string") {
               dict_target[a_item[0]] = [ dict_target[a_item[0]] ];
           }
           dict_target[a_item[0]].push(a_item[1]);
        }
        else {
           dict_target[a_item[0]] = a_item[1];
        }
    });
 } // if -- proceed

У меня нет ', который вы добавили в строку. Я не могу использовать функцию JSON.parse. Кроме того, я не хочу повторять объект, но знаю, смогу ли я его проанализировать перед

IsraGab 24.07.2018 17:32

@IsraGab Исправил решение. Если синтаксический анализ завершится успешно, вы узнаете, что можете его проанализировать. Вы можете проверить это перед использованием регулярного выражения. Использование их в качестве замены для парсеров, как правило, делает их сложными и трудными в обслуживании, поэтому я бы попытался избежать этого варианта использования, но ваши настройки, конечно, могут быть другими.

collapsar 24.07.2018 17:42

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

IsraGab 24.07.2018 17:45

Было бы чище просто заменить каждый ключ / значение в строке кавычками вместо нескольких замен? src.replace(/([\w\.]+)/,'"$1"');

Sunny Patel 24.07.2018 17:54

Извините, я забыл добавить глобальный флаг g. Это все еще в силе. src.replace(/([\w\.]+)/g,'"$1"');

Sunny Patel 24.07.2018 18:08

@SunnyPatel Regex, как известно, сложно поддерживать, поэтому я предпочитаю, чтобы они были как можно более читабельными (YMMV в конкретизации концепции, конечно), даже если это приводит к снижению производительности. Если последнее оказывается проблемой, оптимизация обычно проста.

collapsar 24.07.2018 18:17

Я не согласен, если вы предполагаете, что одно из наших выражений трудно читать и / или поддерживать. На мой взгляд, они оба довольно прямолинейны. Но эй, практика ведет к совершенству, не так ли? :)

Sunny Patel 24.07.2018 18:32

@SunnyPatel Мы вернемся к этой теме через 3 месяца ...;) Как я уже писал, все работает.

collapsar 25.07.2018 00:22

Вот код, который сначала проверяет строку и выводит результат. Не совсем оптимально, но отлично справляется с задачей.

var string = '[[abc.d.2,mcnv.3.we],[abec.d.2,mcnv.4.we],[abhc.d.2,mcnv.5.we]]';
var result = (/^\[(\[.*\..*\..*\,.*\..*\..*\]\,)*\[(.*\..*\..*\,.*\..*\..*)\]\]$/g).exec(string);
if (result) {
  var r1 = result[1].replace(/\[|\]/g, '').split(',');
  var r2 = result[2].split(',');
  var output = {};

  for (var i = 0; i < r1.length -1; i +=2) {
    output[r1[i]] = r1[i+1];
  }
  output[r2[0]] = r2[1];

  console.info(output);
} else {
  console.info('invalid string');
}

Ваше регулярное выражение - довольно тяжело возвращаться с этими жадными .*.

Sunny Patel 24.07.2018 18:27

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

Satya Sampathirao 24.07.2018 18:35

Мое кодовое решение для гольфа ...

const parse = (str) => {
    let obj = {};
    str.replace(
        /\[([^\[,]+),([^\],]+)\]/g,
        (m, k, v) => obj[k] = v
    );
    return obj;
};

Преимущества:

  • Более разрешено использование произвольных символов
  • Более толерантный к отсутствующим значениям
  • Избегает одноразовых предметов для GC

Недостатки:

  • Более разрешено использование произвольных символов!
  • Это неправильный парсер ...
  • Не имеет контекста, просто [ключ, значение]

На самом деле я хотел опубликовать в качестве своего ответа следующее ... но я думаю, что это доставит мне неприятности: P

const parse=(str,obj = {})=>
!str.replace(/\[([^\[,]+),([^\],]+)\]/g,(m,k,v)=>obj[k]=v)||obj;

Другие вопросы по теме