Я хотел бы разобрать эту строку:
[[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"
}
Сначала я хотел бы проверить, можно ли проанализировать строку, чтобы сделать ее ключ => значение. Как я могу проверить строку, если она содержит пары?
Спасибо
Ожидаете ли вы большего количества уровней вложенности?
@UnbearableLightness нет
@UnbearableLightness Тогда вам стоит поделиться своими усилиями, о которых идет речь. Также в отношении .* в нем будет учитываться даже запятая. Попытайтесь быть более конкретным
@IsraGab ты что-то вроде \[\[([^,]+),([^\]]+)],\[([^,]+),([^\]]+)],\[([^,]+),([^\]]+)\]\]? Попробуйте здесь. Заменить на {\n"\1": "\2",\n"\3": "\4",\n"\5": "\6",\n}
Нет: я обновил регулярное выражение, которое вы отправили, фактической строкой, которую мне нужно проанализировать. Строка, которую я публикую здесь, является примером, но реальная строка намного больше, чем эта: regex101.com/r/GReD6H/2
Тогда вам понадобится цикл, поскольку рекурсия не поддерживается в регулярном выражении Javascript.
По какой причине вы конкретно используете регулярное выражение? Не можете ли вы проанализировать его как двумерный массив и использовать javascript для проверки дубликатов? [["abc.d.2", "mcnv.3.we"], ["abec.d.2", "mcnv.4.we"], ["abhc.d.2", "mcnv.5.we"]]
@ Arye Dov Eidelman, строка поступает из уведомления веб-сокета, я не знаю, как будут выглядеть данные в сокете, поэтому я хотел бы проверить, какое регулярное выражение соответствует строке, чтобы отправить ее в нужную функцию



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете попробовать что-то вроде этого:
Идея:
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)Идея:
[...:...][ и ].,.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, ты тоже можешь это сделать. Но для этого потребуется больше профессии. У вас может быть регулярное выражение для сопоставления текста между [], а затем разбить его с помощью строки. Если хочешь, могу завтра добавить отрывок.
@ Раджеш, да, пожалуйста. Меня не волнует профессия, но, возможно, в следующий раз у меня будет по 3 элемента в каждом подмассиве, тогда я отправлю строку в функцию сопоставления для создания объекта. В текущем решении 2 жестко запрограммирован, он должен быть параметром в вызове функции
У меня также есть еще одна проблема с вашим регулярным выражением. Он не проверяет [[]], поэтому я могу иметь простую строку, которая также будет соответствовать: abc.d.2, mcnv.3.we, [abec.d.2, mcnv.4.we, abhc.d. 2, mcnv.5. мы
@IsraGab Я обновил свой ответ обсуждаемым подходом. Надеюсь, поможет!
Разберите массив как 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 Исправил решение. Если синтаксический анализ завершится успешно, вы узнаете, что можете его проанализировать. Вы можете проверить это перед использованием регулярного выражения. Использование их в качестве замены для парсеров, как правило, делает их сложными и трудными в обслуживании, поэтому я бы попытался избежать этого варианта использования, но ваши настройки, конечно, могут быть другими.
Да. Я сейчас тестирую ваше решение. Я хотел бы сначала проверить строку, чтобы узнать, могу ли я ее проанализировать, но, возможно, вы правы, манипулируя строкой, чтобы я мог ее проанализировать.
Было бы чище просто заменить каждый ключ / значение в строке кавычками вместо нескольких замен? src.replace(/([\w\.]+)/,'"$1"');
Извините, я забыл добавить глобальный флаг g. Это все еще в силе. src.replace(/([\w\.]+)/g,'"$1"');
@SunnyPatel Regex, как известно, сложно поддерживать, поэтому я предпочитаю, чтобы они были как можно более читабельными (YMMV в конкретизации концепции, конечно), даже если это приводит к снижению производительности. Если последнее оказывается проблемой, оптимизация обычно проста.
Я не согласен, если вы предполагаете, что одно из наших выражений трудно читать и / или поддерживать. На мой взгляд, они оба довольно прямолинейны. Но эй, практика ведет к совершенству, не так ли? :)
@SunnyPatel Мы вернемся к этой теме через 3 месяца ...;) Как я уже писал, все работает.
Вот код, который сначала проверяет строку и выводит результат. Не совсем оптимально, но отлично справляется с задачей.
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');
}Ваше регулярное выражение - довольно тяжело возвращаться с этими жадными .*.
Да, я знаю. Вот почему я упомянул, что это не оптимальное решение :) Производительность не имеет значения, если вы разбираете небольшую строку. Но это был бы другой случай, когда разбор огромных CSV-файлов с такой логикой.
Мое кодовое решение для гольфа ...
const parse = (str) => {
let obj = {};
str.replace(
/\[([^\[,]+),([^\],]+)\]/g,
(m, k, v) => obj[k] = v
);
return obj;
};
Преимущества:
Недостатки:
На самом деле я хотел опубликовать в качестве своего ответа следующее ... но я думаю, что это доставит мне неприятности: P
const parse=(str,obj = {})=>
!str.replace(/\[([^\[,]+),([^\],]+)\]/g,(m,k,v)=>obj[k]=v)||obj;
Я пробовал это: ([. *?,. *?]) Но пары недостаточно :( Кстати: я никогда не задаю вопрос, если я не пробовал несколько часов назад