【问题标题】:Typescript get distinct values from an object打字稿从对象中获取不同的值
【发布时间】:2020-10-14 21:18:48
【问题描述】:

如何在 javascript 中编写select distinct country, state from myObject

Array.from(new Set(myObject.map(item => item.country))) 将返回不同的国家。我如何在地图中添加国家、州和其他列???

输入数据:

const myObject = [
  {
    country: 'USA',
    state: 'Missouri',
    county: 'County1',
  },
  {
    country: 'USA',
    state: 'Missouri',
    county: 'County2',
  },
  {
    country: 'Canada',
    state: 'Alberta',
    county: 'County3',
  },
];

为了获得独特的国家,我会写 Array.from(new Set(myObject.map(item => item.country))) 结果将是 ['USA', 'Canada']

如果想要结果应该怎么写

[
  {
    country: 'USA',
    state: 'Missouri',
  },
  {
    country: 'Canada',
    state: 'Alberta',
  },
]

这包含独特的国家和州组合

【问题讨论】:

  • 您能否提供输入数据和预期结果的示例?不确定这是否是您要查找的内容stackoverflow.com/questions/56633869/…
  • 我用示例数据和预期结果编辑了问题。
  • @diedu 我不知道你为什么认为这个问题与 TypeScript 无关?
  • 我更新了my answer 以使用您的示例。如果它没有解决您的用例,请详细说明。

标签: javascript angular typescript


【解决方案1】:

根据参考答案,您可以使用Mapspread operator,如下所示

https://stackoverflow.com/a/63274702/4964569

const myObject = [
  { country: 'USA', state: 'Missouri', county: 'County1' },
  { country: 'USA', state: 'Missouri', county: 'County2' },
  { country: 'Canada', state: 'Alberta', county: 'County3' },
];

let data = new Map();

for (let obj of myObject) {
  delete obj.county;
  data.set(obj.country, obj);
}

let unique = [...data.values()];

console.log(unique);

【讨论】:

  • 那行得通.. 谢谢.. 但是我的对象有大约 60 个字段,我想在一个场景中考虑/映射 3 个值,在另一种场景中考虑 / 映射 8 个值。考虑到我拥有的字段数量,是否可以对其进行更新以使其更具动态???
  • 如果您有多个不同的 country/state 对,此解决方案将不起作用。
【解决方案2】:

以下代码应采用对象数组和这些对象的键列表,并返回表示该组键的不同值的对象数组。我假设这些键的属性类型只有stringnumberboolean

function distinct<T extends Record<K, string | number | boolean>,
  K extends keyof T>(arr: T[], ...keys: K[]): Pick<T, K>[] {
  const key = (obj: T) => JSON.stringify(keys.map(k => obj[k]));
  const val = (obj: T) => keys.reduce((a, k) => (a[k] = obj[k], a), {} as Pick<T, K>);
  const dict = arr.reduce((a, t) => (a[key(t)] = val(t), a), {} as { [k: string]: Pick<T, K> })
  return Object.values(dict);
}

我们的想法是获取数组中的每个对象,用JSON.stringify() 序列化它的属性元组,并将这个序列化的字符串用作字典键。我们在该键上放置的值是一个仅由这些属性的值组成的对象。通过使用字典,我们保证在我们关心的键上,每组不同的属性只会出现一个对象。然后我们把这个字典的值变成一个数组。

如果我在您的 myObject 示例上对其进行测试,结果如下:

const result = distinct(myObject, "country", "state");
console.log(result);
/*  [{ "country": "USA", "state": "Missouri" }, { "country": "Canada", "state": "Alberta" }] */

这就是你想要的。让我们也测试一下我现在编写的一些类型和数组:

interface MyObject {
  country: string,
  state: string,
  age: number,
  name: string
}
const arr: MyObject[] = [
  { name: "Alice", age: 35, country: "USA", state: "MA" },
  { name: "Bob", age: 40, country: "USA", state: "MI" },
  { name: "Carmen", age: 35, country: "Mexico", state: "BC" },
  { name: "Danilo", age: 35, country: "Mexico", state: "MI" }
]

所以我们有一个MyObject 数组。让我们获取不同的 country 值:

const distinctCountries = distinct(arr, "country"); // Array<{country: string}>
console.log(distinctCountries); // [{ "country": "USA" }, { "country": "Mexico" }] 
console.log(distinctCountries.map(x => x.country)); // USA, Mexico

注意结果是一个{country: string} 值的数组。您可以使用map() 将其转换为strings 的数组。让我们得到不同的 countrystate 值:

const distinctCountriesAndStates = distinct(arr, "country", "state");
console.log(distinctCountriesAndStates);
/* [{ "country": "USA", "state": "MA" }, { "country": "USA", "state": "MI" }, 
{ "country": "Mexico", "state": "BC" }, { "country": "Mexico", "state": "MI" }] */

这里是{country: string, state: string} 对象的数组。不确定您想如何表示它们,但您可以使用map() 来按您认为合适的方式按摩它们。最后让我们得到不同的countryage 值:

const distinctAgesAndCountries = distinct(arr, "country", "age");
console.log(distinctAgesAndCountries);
/* [{ "country": "USA", "age": 35 }, { "country": "USA", "age": 40 },
 { "country": "Mexico", "age": 35 }] */

这是{country: string, age: number} 对象的数组。

无论如何,希望能给你一些方向。

Playground link to code

【讨论】:

  • 感谢您花时间详细解释。这对我来说非常有效。而且这种独特的方法接受动态参数,这使我的工作非常容易,因为我每次都必须将它用于不同的参数。
【解决方案3】:

下面是使用reduce的解决方案;

const myObject = [
  { country: 'USA', state: 'Missouri', county: 'County1' },
  { country: 'USA', state: 'Missouri', county: 'County2' },
  { country: 'Canada', state: 'Alberta', county: 'County3' },
];

const unique = myObject.reduce((prev, {country, state}) => 
  prev.some(x => x.country === country && x.state === state )? prev: [...prev, {country, state} ], [])

   console.log(unique )

【讨论】:

    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 2018-07-03
    • 2021-11-02
    • 2020-10-05
    相关资源
    最近更新 更多