Разобрать массив и превратить значения в объект - PullRequest
0 голосов
/ 24 октября 2019

У меня есть массив, который мне нужно превратить в объект с заданными значениями.

Это входной массив

let actions = ['CREATE: id=14&amount=800&currency=USD','FINALIZE: id=14&amount=800&currency=USD','PAY: id=14' 
]

Как мне превратить его в этот объект.

let result ={
 'create': 800,
 'finalize': 800,
 'pay':14
}

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

for(let x = 0; x <=actions.length;x++){
    if(actions[x].icludes('CREATE')){

    } else(actions[x].icludes('FINALIZE')){

    } else(actions[x].icludes('PAY')){

    }
}

Помощь муравья приветствуется.

Ответы [ 4 ]

2 голосов
/ 24 октября 2019

Вы можете разбить каждую строку на :\s+, чтобы получить ключ и строку для анализа. Вы получите 2 значения в результирующем массиве. Используйте destructuring , чтобы получить их для разделения переменных

["CREATE", "id=14&amount=800&currency=USD"]

Затем используйте конструктор URLSearchParams для второго значения, чтобы получить пару ключ-значение из строки запроса.

Для некоторых ключей требуется amount, а для некоторых ключей необходимо значение id. Таким образом, вы можете создать объект Mapper. Это сопоставляет ключ с именем для поиска в URLSearchParams.

const mapper = {
  PAY: "id",
  CREATE: 'amount',
  FINALIZE: 'amount',
  default: "amount"
};

Здесь PAY необходимо значение id. Если у вас есть больше ключей, вы можете добавить их здесь. Вы также можете добавить CREATE: "amount" к этому объекту. Но, поскольку это default, я пропустил это. Ключ default можно использовать, если ключ не найден в mapper. Вернуть объект с ключом и значением из функции разбора.

Затем reduce массив и объединить каждый проанализированный объект для создания выходных данных

const actions = ['CREATE: id=14&amount=800&currency=USD', 'FINALIZE: id=14&amount=800&currency=USD', 'PAY: id=14']

const mapper = {
  PAY: "id",
  //CREATE: 'amount', // you could add CREATE and FINALIZE if you want
  default: "amount"
};

function parse(str) {
  const [key, value] = str.split(/:\s+/);
  const param = new URLSearchParams(value).get(mapper[key] || mapper.default);
  return { [key.toLowerCase()]: param };
}

const output = actions.reduce((acc, str) => Object.assign(acc, parse(str)), {});

console.log(output)
0 голосов
/ 24 октября 2019

Вот решение:

let actions = ['CREATE: id=14&amount=800&currency=USD','FINALIZE: id=14&amount=800&    currency=USD','PAY: id=14']
let actionObject = [];

for(let i=0;i<actions.length;i++){

    // Split where it has colon and space
    let splitter = actions[i].split(": ");

    // Get label (and make it lowercase)
    let theLabel = splitter[0].toLowerCase();

    // remove label from array
    splitter.splice(0,1);

    // rejoin array if any values contained colon and space
    splitter = splitter.join(": ");

    // find amount= and split that
    splitter2 = splitter.split("amount=");

    // splitter2[1] will be everything after "amount="
    // if amount= didn't exist it will be undefined
    if(splitter2[1] !== undefined){
        // Now we just split the other side of the amount where &
        // if amount is the last thing and there's no &, it won't matter
        splitter2 = splitter2[1].split("&");

        // Now create the key (l1) and value (splitter2[0])
        actionObject[l1] = splitter2[0];
    }else{
        // If amount is not found, we get id instead, same process
        splitter2 = splitter.split("id=");
        if(splitter2[1] !== undefined){
            splitter2 = splitter2[1].split("&");
            actionObject[l1] = splitter2[0];
        }
    }
}

Итак, теперь у вас есть объект actionObject, и он содержит суммы, но только для значений, которые содержат сумму или идентификатор.

actionObject {
    create: "800",
    finalize: "800",
    pay: "14"
}
0 голосов
/ 24 октября 2019

В качестве примера регулярного выражения это также может работать. Конечно, всегда может быть более надежное правило регулярных выражений. (и более масштабируемый)

let actions = [
  'CREATE: id=14&amount=800&currency=USD',
  'FINALIZE: id=14&amount=800&currency=USD',
  'PAY: id=14' 
]

let result = actions.reduce((acc, item) => {
  if (item.match(/^CREATE:.+amount=(\d+)/)) {
    acc.create = item.match(/^CREATE:.+amount=(\d+)/)[1];
  } else if (item.match(/^FINALIZE:.+amount=(\d+)/)) {
    acc.finalize = item.match(/^FINALIZE:.+amount=(\d+)/)[1];
  } else if (item.match(/^PAY:.+id=(\d+)/)) {
    acc.id = item.match(/^PAY:.+id=(\d+)/)[1];
  };
  return acc;
}, {})

console.log(result);
0 голосов
/ 24 октября 2019

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

const actions = [
  'CREATE: id=14&amount=800&currency=USD',
  'FINALIZE: id=14&amount=800&currency=USD',
  'PAY: id=14' 
];

const actionsData = actions.reduce((res, str) => {
  const [op, query] = str.split(': '); 
  
  const kvPairs = query.split('&');
  
  const data = kvPairs.reduce((res, kvStr) => {
    const [key, value] = kvStr.split('=');
    res[key] = value;
    return res;
  }, {});
  
  res[op] = data;
  return res;
}, {});

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