将对象与键值匹配模式组合在一起。

huangapple go评论52阅读模式
英文:

Combine object with key values matching to pattern

问题

我正在尝试基于以S.1开头的键来拆分对象。

const obj = {
  "S.1.1.0": "Hi",
  "S.1.1.1": "what is your name",
  "S.1.1.2": "Can we meet",
  "S.2.1.1": "what is the time now",
  "S.2.1.2a": "It is 6 PM",
  "S.3.1.1b": "where do you live",
  "S.3.1.2": "how is the weather",
  "S.3.1.3": "it is very cold",
  "S.3.1.3b": "yes",
}

const result = Object.entries(obj).reduce((a, [key, val]) => { 
  const [s, k, v] = key.split('.')
  const item = a.find(({ key: itemkey }) => itemkey === k)
  console.log(item)
  if (item) {  
    item[v] = val
  } else {  
    a.push({
      key: k,
      [v]: val
    })
  }

  return a
})

console.log(result)

期望的输出是键值以S.1开头的组合在一起。键值是动态的,始终以S.1,S.2 ...开头。

[{
  "S.1.1.0": "Hi",
  "S.1.1.1": "what is your name",
  "S.1.1.2": "Can we meet"
},
{
  "S.2.1.1": "what is the time now",
  "S.2.1.2a": "It is 6 PM"
},
{
  "S.3.1.1b": "where do you live",
  "S.3.1.2": "how is the weather",
  "S.3.1.3": "it is very cold",
  "S.3.1.3b": "yes"
}]
英文:

I am trying to split the object based on the keys starting with a pattern like S.1.1.0.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const obj = {
  &quot;S.1.1.0&quot;: &quot;Hi&quot;,
  &quot;S.1.1.1&quot;: &quot;what is your name&quot;,
  &quot;S.1.1.2&quot;: &quot;Can we meet&quot;,
  &quot;S.2.1.1&quot;: &quot;what is the time now&quot;,
  &quot;S.2.1.2a&quot;: &quot;It is 6 PM&quot;,
  &quot;S.3.1.1b&quot;: &quot;where do you live&quot;,
  &quot;S.3.1.2&quot;: &quot;how is the weather&quot;,
  &quot;S.3.1.3&quot;: &quot;it is very cold&quot;,
  &quot;S.3.1.3b&quot;: &quot;yes&quot;,
}

const result = Object.entries(obj).reduce((a, [key, val]) =&gt; { 
  const [s, k, v] = key.split(&#39;.&#39;)  
  const item = a.find(({
    key: itemkey
  }) =&gt; itemkey === k)  
 console.log(item)
  if (item) {  
    item[v] = val
  } else {  
    a.push({
      key: k,
      [v]: val
    })
  }

  return a
}, [])

console.log(result)

<!-- end snippet -->

Expecting the output to be like where key value starting with S.1 combined together. The key value is dynamic by always starts like S.1, S.2 ...

 [{
        &quot;S.1.1.0&quot;: &quot;Hi&quot;,
        &quot;S.1.1.1&quot;: &quot;what is your name&quot;,
        &quot;S.1.1.2&quot;: &quot;Can we meet&quot;
      },
      {
        &quot;S.2.1.1&quot;: &quot;what is the time now&quot;,
        &quot;S.2.1.2a&quot;: &quot;It is 6 PM&quot;
      },
      {
        &quot;S.3.1.1b&quot;: &quot;where do you live&quot;,
        &quot;S.3.1.2&quot;: &quot;how is the weather&quot;,
        &quot;S.3.1.3&quot;: &quot;it is very cold&quot;,
        &quot;S.3.1.3b&quot;: &quot;yes&quot;
      }
    ]

答案1

得分: 2

你可以使用reduce()方法创建一个带有mapping键作为索引的对象。然后使用Object.values(result)来获取所需的结果。

[
  {
    "S.1.1.0": "Hi",
    "S.1.1.1": "what is your name",
    "S.1.1.2": "Can we meet"
  },
  {
    "S.2.1.1": "what is the time now",
    "S.2.1.2a": "It is 6 PM"
  },
  {
    "S.3.1.1b": "where do you live",
    "S.3.1.2": "how is the weather",
    "S.3.1.3": "it is very cold",
    "S.3.1.3b": "yes"
  }
]
英文:

You could reduce() to an object with the mapping key as index.

Then use Object.values(result) to get the desired result

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const obj = {
  &quot;S.1.1.0&quot;: &quot;Hi&quot;,
  &quot;S.1.1.1&quot;: &quot;what is your name&quot;,
  &quot;S.1.1.2&quot;: &quot;Can we meet&quot;,
  &quot;S.2.1.1&quot;: &quot;what is the time now&quot;,
  &quot;S.2.1.2a&quot;: &quot;It is 6 PM&quot;,
  &quot;S.3.1.1b&quot;: &quot;where do you live&quot;,
  &quot;S.3.1.2&quot;: &quot;how is the weather&quot;,
  &quot;S.3.1.3&quot;: &quot;it is very cold&quot;,
  &quot;S.3.1.3b&quot;: &quot;yes&quot;,
}

const result = Object.entries(obj).reduce((a, [key, val]) =&gt; { 
  const mapping = key.split(&#39;.&#39;, 2).join(&#39;.&#39;);
  
  if (!a[mapping]) a[mapping] = { };
  a[mapping][key] = val;
  
  return a;
}, {})

const resultArray = Object.values(result);

console.log(resultArray)

<!-- end snippet -->

Output:

[
  {
    &quot;S.1.1.0&quot;: &quot;Hi&quot;,
    &quot;S.1.1.1&quot;: &quot;what is your name&quot;,
    &quot;S.1.1.2&quot;: &quot;Can we meet&quot;
  },
  {
    &quot;S.2.1.1&quot;: &quot;what is the time now&quot;,
    &quot;S.2.1.2a&quot;: &quot;It is 6 PM&quot;
  },
  {
    &quot;S.3.1.1b&quot;: &quot;where do you live&quot;,
    &quot;S.3.1.2&quot;: &quot;how is the weather&quot;,
    &quot;S.3.1.3&quot;: &quot;it is very cold&quot;,
    &quot;S.3.1.3b&quot;: &quot;yes&quot;
  }
]

答案2

得分: 0

如果要提高效率,可以创建一个Map,并根据keyFn指定的条件对每个键值对进行分组。

const keyFn = (prop) => prop.match(/(?<=S\.)\d+/)[0]

示例

以下是代码的示例:

const obj = {
  "S.1.1.0": "Hi",
  "S.1.1.1": "what is your name",
  "S.1.1.2": "Can we meet",
  "S.2.1.1": "what is the time now",
  "S.2.1.2a": "It is 6 PM",
  "S.3.1.1b": "where do you live",
  "S.3.1.2": "how is the weather",
  "S.3.1.3": "it is very cold",
  "S.3.1.3b": "yes",
}

const groupBy = (obj, keyFn) =>
  [...Object
    .entries(obj)
    .reduce((map, [prop, value]) => {
        const key = keyFn(prop), entries = map.get(key) ?? [];
        entries push([prop, value]);
        return map.set(key, entries);
      }, new Map)
    .values()]
    .map(entries => Object.fromEntries(entries))

const grouped = groupBy(obj, (prop) => prop.match(/(?<=S\.)\d+/)[0]);

console.log(grouped);

以下是使用lodash的相同示例。我创建了一个混入函数,接受一个对象和一个键模式。

const obj = {
  "S.1.1.0": "Hi",
  "S.1.1.1": "what is your name",
  "S.1.1.2": "Can we meet",
  "S.2.1.1": "what is the time now",
  "S.2.1.2a": "It is 6 PM",
  "S.3.1.1b": "where do you live",
  "S.3.1.2": "how is the weather",
  "S.3.1.3": "it is very cold",
  "S.3.1.3b": "yes",
}

_.mixin({
  groupByPattern : (object, keyPattern) =>
    _.chain(obj)
      .entries()
      .groupBy(([prop, value]) => prop.match(keyPattern)?.[0])
      .values()
      .map(_.fromPairs)
      .value()
});

const grouped = _.groupByPattern(obj, /(?<=S\.)\d+/);

console.log(grouped);

希望对你有帮助。

英文:

If you want to be efficient, you can build a Map and bin each key-value pair by criteria specified by the keyFn.

const keyFn = (prop) =&gt; prop.match(/(?&lt;=S\.)\d+/)[0]

Example

Here is the code in action:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const obj = {
  &quot;S.1.1.0&quot;: &quot;Hi&quot;,
  &quot;S.1.1.1&quot;: &quot;what is your name&quot;,
  &quot;S.1.1.2&quot;: &quot;Can we meet&quot;,
  &quot;S.2.1.1&quot;: &quot;what is the time now&quot;,
  &quot;S.2.1.2a&quot;: &quot;It is 6 PM&quot;,
  &quot;S.3.1.1b&quot;: &quot;where do you live&quot;,
  &quot;S.3.1.2&quot;: &quot;how is the weather&quot;,
  &quot;S.3.1.3&quot;: &quot;it is very cold&quot;,
  &quot;S.3.1.3b&quot;: &quot;yes&quot;,
}

const groupBy = (obj, keyFn) =&gt;
  [...Object
    .entries(obj)
    .reduce((map, [prop, value]) =&gt; {
        const key = keyFn(prop), entries = map.get(key) ?? [];
        entries.push([prop, value]);
        return map.set(key, entries);
      }, new Map)
    .values()]
    .map(entries =&gt; Object.fromEntries(entries))

const grouped = groupBy(obj, (prop) =&gt; prop.match(/(?&lt;=S\.)\d+/)[0]);

console.log(grouped);

<!-- language: lang-css -->

.as-console-wrapper { top: 0; max-height: 100% !important; }

<!-- end snippet -->

Here is the same, but it uses lodash. I created a mixin that takes an object and a key pattern.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const obj = {
  &quot;S.1.1.0&quot;: &quot;Hi&quot;,
  &quot;S.1.1.1&quot;: &quot;what is your name&quot;,
  &quot;S.1.1.2&quot;: &quot;Can we meet&quot;,
  &quot;S.2.1.1&quot;: &quot;what is the time now&quot;,
  &quot;S.2.1.2a&quot;: &quot;It is 6 PM&quot;,
  &quot;S.3.1.1b&quot;: &quot;where do you live&quot;,
  &quot;S.3.1.2&quot;: &quot;how is the weather&quot;,
  &quot;S.3.1.3&quot;: &quot;it is very cold&quot;,
  &quot;S.3.1.3b&quot;: &quot;yes&quot;,
}

_.mixin({
  groupByPattern : (object, keyPattern) =&gt;
    _.chain(obj)
      .entries()
      .groupBy(([prop, value]) =&gt; prop.match(keyPattern)?.[0])
      .values()
      .map(_.fromPairs)
      .value()
});

const grouped = _.groupByPattern(obj, /(?&lt;=S\.)\d+/);

console.log(grouped);

<!-- language: lang-css -->

.as-console-wrapper { top: 0; max-height: 100% !important; }

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年3月15日 20:08:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75744490.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定