【问题标题】:Parse array and turn values into an object解析数组并将值转换为对象
【发布时间】:2019-10-24 15:27:51
【问题描述】:

我有一个数组,我需要将其转换为具有给定值的对象。

这是输入数组

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')){

    }
}

感谢 Ant 的帮助。

【问题讨论】:

    标签: javascript arrays regex


    【解决方案1】:

    您可以在:\s+ 处拆分每个字符串以获取密钥和要解析的字符串。您将在结果数组中获得 2 个值。使用destructuring 让它们分隔变量

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

    然后在第二个值上使用URLSearchParams构造函数从查询字符串中获取一个键值对。

    有些键需要amount,而有些键需要id 的值。因此,您可以创建一个映射器对象。这会将键与要在 URLSearchParams 中搜索的 name 映射。

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

    这里,PAY 需要 id 值。如果您有更多密钥,可以在此处添加。您也可以将CREATE: "amount" 添加到此对象。但是,因为那是default,我已经跳过了。如果在mapper 中找不到密钥,则可以使用default 密钥。从 parse 函数返回一个带有键和值的对象。

    然后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)

    【讨论】:

    • 华丽的方法
    • 我其实很喜欢这种方法,谢谢,您的解释非常直截了当。
    【解决方案2】:

    考虑到您的预期输出不遵循单一结构,我选择返回所有值,而不是任意值。但是,如果您有一些业务逻辑来证明选择不同的返回值是合理的,那么您可以轻松地更改代码以适应这种情况。

    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);

    【讨论】:

      【解决方案3】:

      作为一个正则表达式示例,这也可以工作。当然,可能总是有更强大的正则表达式规则。 (并且更具可扩展性)

      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);
      

      【讨论】:

        【解决方案4】:

        这里有一个解决方案:

        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,它包含数量,但仅限于包含数量或 id 的值。

        actionObject {
            create: "800",
            finalize: "800",
            pay: "14"
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-08-03
          • 2021-07-23
          • 1970-01-01
          • 2019-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-26
          相关资源
          最近更新 更多