根据键过滤对象,然后根据键和值构造新的对象数组

Filtering an object based on key, then constructing new array of objects based on the keys and values

如果问题措辞怪异,我们深表歉意,但通过示例更容易解释。

假设我有一个 json 包含

[
    {
      "UID": 84001001,
      "iso2": "US",
      "iso3": "USA",
      "code3": 840,
      "FIPS": 1001,
      "Admin2": "Autauga",
      "Province_State": "Alabama",
      "Country_Region": "US",
      "Lat": 32.53952745,
      "Long_": -86.64408227,
      "Combined_Key": "Autauga, Alabama, US",
      "1/22/20": 0,
      ... so on and so on ...
      "5/27/21": 21606
    },
    {
      "UID": 84001003,
      "iso2": "US",
      "iso3": "USA",
      "code3": 840,
      "FIPS": 1003,
      "Admin2": "Baldwin",
      "Province_State": "Alabama",
      "Country_Region": "US",
      "Lat": 30.72774991,
      "Long_": -87.72207058,
      "Combined_Key": "Baldwin, Alabama, US",
      "1/22/20": 0,
      ... so on and so on ...
      "5/27/21": 21606
    },
...
]

并且此 json 继续适用于美国所有州的所有县。

我有两个反应状态变量,USStatecounty。如果我们遍历 json 和 USState === currState.Province_Statecounty === currState.Admin2 中的每个 currState,那么我想要那个对象。

示例:如果 USState = "Alabama"county = "Baldwin",则此对象将包含:

dataObject = {
      "UID": 84001003,
      "iso2": "US",
      "iso3": "USA",
      "code3": 840,
      "FIPS": 1003,
      "Admin2": "Baldwin",
      "Province_State": "Alabama",
      "Country_Region": "US",
      "Lat": 30.72774991,
      "Long_": -87.72207058,
      "Combined_Key": "Baldwin, Alabama, US",
      "1/22/20": 0,
      ... so on and so on ...
      "5/27/21": 21606
    }

这部分我已经完成了。我有一个像上面那样的 dataObject。我不想为此包含我的代码,因为它与 React 更相关,而且这个问题更适合 JavaScript 和 json.

现在,我想过滤此对象以仅包含日期,所以现在 dataObject 将包含

dataObject = {
      "1/22/20": 0,
      ... so on and so on ...
      "5/27/21": 21606
    }

然后最后,我想根据这些键值对构造一个数组得到

array = [ 
            { x : new Date(2020, 01, 22), y : 0}, 
            ..., 
            { x : new Date(2021, 05, 27), y : 21606}
        ]

所以我可以使用 Canvas.js 绘制它。

然而,作为 React 的初学者,我发现自己变得困惑和路障,不断使用 mapfilter 函数,同时也习惯了这种编程风格。我认为我正在使这种方式变得比需要的更难或更复杂。这也是我第一次处理 json.

基本上,我只想过滤我的 dataObject 以仅包含带日期的键,然后绘制这些日期(键)与它们的数字(值)。我将不胜感激任何帮助。谢谢

您可以按照您的描述使用 filtermap 来做到这一点,首先通过 Object.entries 将对象转换为 [key, value] 对的数组, 见评论:

// A regular expression for your date format
const rexDate = /^(?<month>\d{1,2})\/(?<day>\d{1,2})\/(?<year>\d{2})$/;
// 1. Convert the object to a [key, value] array
// 2. Filter out the properties whose keys don't match the regex
// 3. Map the surviving properties to the object you want
const array = Object.entries(dataObject)
    .filter(([key]) => rexDate.test(key)) // Is it a date according to our regex?
    .map(([key, value]) => {
        // Get the capture group using their names
        const {groups: {month, day, year}} = rexDate.exec(key);
        // Build the object
        return {
            x: new Date(Number(year) + 2000, Number(month) - 1, Number(day)),
            y: value
        };
    });

实例:

const dataObject = {
    "UID": 84001003,
    "iso2": "US",
    "iso3": "USA",
    "code3": 840,
    "FIPS": 1003,
    "Admin2": "Baldwin",
    "Province_State": "Alabama",
    "Country_Region": "US",
    "Lat": 30.72774991,
    "Long_": -87.72207058,
    "Combined_Key": "Baldwin, Alabama, US",
    "1/22/20": 0,
    // ... so on and so on ...
    "5/27/21": 21606
};

const rexDate = /^(?<month>\d{1,2})\/(?<day>\d{1,2})\/(?<year>\d{2})$/;
const array = Object.entries(dataObject)
    .filter(([key]) => rexDate.test(key)) // Is it a date according to our regex?
    .map(([key, value]) => {
        // Get the capture group using their names
        const {groups: {month, day, year}} = rexDate.exec(key);
        // Build the object
        return {
            x: new Date(Number(year) + 2000, Number(month - 1), Number(day)),
            y: value
        };
    });
console.log(array);

(代码段控制台将日期显示为字符串,但它们是实际对象中的 Date 个实例。)

我在那里使用了命名捕获组,这是相当新的但在现代浏览器中得到了很好的支持,但您可以改用匿名的。

我还使用 Number 将字符串转换为数字,但我在 中介绍了各种其他选项。

该版本最终为每个 属性 执行正则表达式两次。您可以通过再次传递数据来避免这种情况,但这可能不值得。

您也可以使用 for-in 循环来执行此操作,全部通过一次:

const rexDate = /^(?<month>\d{1,2})\/(?<day>\d{1,2})\/(?<year>\d{2})$/;
const array = [];
// This strange-looking thing creates a function that you call with an object and
// a key to see if the object has an "own" property with that key.
const hasOwn = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
for (const key in dataObject) {
    // If this is an "own" property of the object, try to match it with the
    // regular expression; bail if it's not an own property or doesn't match
    let match;
    if (!hasOwn(dataObject, key) || !(match = rexDate.exec(key))) {
        continue;
    }
    // Get the capture group values using their names
    const {groups: {month, day, year}} = match;
    // Build the object and add it to the array
    array.push({
        x: new Date(Number(year) + 2000, Number(month - 1), Number(day)),
        y: dataObject[key]
    });
}

实例:

const dataObject = {
    "UID": 84001003,
    "iso2": "US",
    "iso3": "USA",
    "code3": 840,
    "FIPS": 1003,
    "Admin2": "Baldwin",
    "Province_State": "Alabama",
    "Country_Region": "US",
    "Lat": 30.72774991,
    "Long_": -87.72207058,
    "Combined_Key": "Baldwin, Alabama, US",
    "1/22/20": 0,
    // ... so on and so on ...
    "5/27/21": 21606
};

const rexDate = /^(?<month>\d{1,2})\/(?<day>\d{1,2})\/(?<year>\d{2})$/;
const array = [];
// This strange-looking thing creates a function that you call with an object and
// a key to see if the object has an "own" property with that key.
const hasOwn = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
for (const key in dataObject) {
    // If this is an "own" property of the object, try to match it with the
    // regular expression; bail if it's not an own property or doesn't match
    let match;
    if (!hasOwn(dataObject, key) || !(match = rexDate.exec(key))) {
        continue;
    }
    // Get the capture group values using their names
    const {groups: {month, day, year}} = match;
    // Build the object and add it to the array
    array.push({
        x: new Date(Number(year) + 2000, Number(month - 1), Number(day)),
        y: dataObject[key]
    });
}
console.log(array);


旁注:您的日期似乎使用两位数年份。我 非常 对使用两位数的年份值持怀疑态度。 :-)