根据键过滤对象,然后根据键和值构造新的对象数组
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 继续适用于美国所有州的所有县。
我有两个反应状态变量,USState
和 county
。如果我们遍历 json 和 USState === currState.Province_State
和 county === 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 的初学者,我发现自己变得困惑和路障,不断使用 map
和 filter
函数,同时也习惯了这种编程风格。我认为我正在使这种方式变得比需要的更难或更复杂。这也是我第一次处理 json.
基本上,我只想过滤我的 dataObject
以仅包含带日期的键,然后绘制这些日期(键)与它们的数字(值)。我将不胜感激任何帮助。谢谢
您可以按照您的描述使用 filter
和 map
来做到这一点,首先通过 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);
旁注:您的日期似乎使用两位数年份。我 非常 对使用两位数的年份值持怀疑态度。 :-)
如果问题措辞怪异,我们深表歉意,但通过示例更容易解释。
假设我有一个 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 继续适用于美国所有州的所有县。
我有两个反应状态变量,USState
和 county
。如果我们遍历 json 和 USState === currState.Province_State
和 county === 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 的初学者,我发现自己变得困惑和路障,不断使用 map
和 filter
函数,同时也习惯了这种编程风格。我认为我正在使这种方式变得比需要的更难或更复杂。这也是我第一次处理 json.
基本上,我只想过滤我的 dataObject
以仅包含带日期的键,然后绘制这些日期(键)与它们的数字(值)。我将不胜感激任何帮助。谢谢
您可以按照您的描述使用 filter
和 map
来做到这一点,首先通过 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);
旁注:您的日期似乎使用两位数年份。我 非常 对使用两位数的年份值持怀疑态度。 :-)