简体   繁体   English

打字稿从对象中获取不同的值

[英]Typescript get distinct values from an object

How do I write select distinct country, state from myObject in javascript.如何在 javascript 中select distinct country, state from myObjectselect distinct country, state from myObject

Array.from(new Set(myObject.map(item => item.country))) would return distinct countries.. How do I add countries, states and other columns in map??? Array.from(new Set(myObject.map(item => item.country)))将返回不同的国家。我如何在地图中添加国家、州和其他列???

Input data:输入数据:

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

To get unique countries, I would write Array.from(new Set(myObject.map(item => item.country))) The result would be ['USA', 'Canada']为了获得独特的国家,我会写 Array.from(new Set(myObject.map(item => item.country))) 结果是 ['USA', 'Canada']

What should I write if want the result to be如果想要结果我应该写什么

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

This contains unique country and state combinations这包含独特的国家和州组合

The following code should take an array of objects and a list of keys of those objects, and return an array of objects representing the distinct values for that set of keys.以下代码应采用对象数组和这些对象的键列表,并返回一个对象数组,表示该组键的不同值。 I assume that the type of properties at those keys will only be string , number , or boolean .我假设这些键的属性类型只会是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);
}

The idea is to take each object in the array, serialize the tuple of its properties at the keys in question with JSON.stringify() , and use this serialized string as a dictionary key.这个想法是获取数组中的每个对象,使用JSON.stringify()在相关键处序列化其属性的元组,并将这个序列化的字符串用作字典键。 The value we put at that key is an object consisting of just the values at those properties.我们放置在该键上的值是一个仅由这些属性的值组成的对象。 By using a dictionary, we guarantee that only one object will appear for each distinct set of properties at the keys we care about.通过使用字典,我们保证对于我们关心的键处的每个不同的属性集,只会出现一个对象。 Then we turn the values of this dictionary into an array.然后我们把这个字典的值变成一个数组。

If I test it on your myObject example, this is what comes out:如果我在您的myObject示例上对其进行测试,结果如下:

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

which is what you wanted.这就是你想要的。 Let's also test it on some type and array that I made up now:让我们也在我现在编写的某种类型和数组上测试它:

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" }
]

So we have an array of MyObject .所以我们有一个MyObject数组。 Let's get the distinct country values:让我们获得不同的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

Notice how what comes out is an array of {country: string} values.注意输出的是一个{country: string}值数组。 You can use map() to turn that into just an array of string s.您可以使用map()将其转换为string数组。 Let's get the distinct country and state values:让我们获得不同的country state值:

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" }] */

Here it's an array of {country: string, state: string} objects.这是一个{country: string, state: string}对象数组。 Not sure how you want to represent those, but you can use map() to massage them as you see fit.不确定你想如何表示这些,但你可以使用map()来按你认为合适的方式按摩它们。 Finally let's get the distinct country and age values:最后让我们得到不同的countryage值:

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

That's an array of {country: string, age: number} objects.这是一个{country: string, age: number}对象数组。

Anyway, hope that gives you some direction.无论如何,希望能给你一些指导。

Playground link to code Playground 链接到代码

Base on referenced answer you can use Map and spread operator as below根据参考答案,您可以使用Mapspread operator ,如下所示

https://stackoverflow.com/a/63274702/4964569 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);

Below is a solution using reduce;以下是使用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 )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM