[英]loop through a json-Array with javascript
i have a problem looping through a json-Array with javascript in nodejs.我在nodejs中循环使用javascript的json数组时遇到问题。 my array called birthdaysArray looks like:
我的名为birthdaysArray 的数组看起来像:
[{"birth":"23.04.1988","name":"Tom Smith"},{"birth":"15.04.2010","name":"Mini Jall"},...,{"birth":"23.04.2001","name":"Michael Bird"},{"birth":"15.11.1999","name":"Frank Middleton"}]
now i want to have an array which list the birthdays (sorted by the day of birth) of the current month.现在我想要一个列出当月生日(按出生日期排序)的数组。 entries with the same day and month (eg 23.04) should be listed in the same date.
具有相同日期和月份(例如 23.04)的条目应在相同日期列出。 it should looks like, if april is the current month (the list has more than 100 entries.):
它应该看起来像,如果4 月是当前月份(列表有 100 多个条目。):
[{"day":"15","name":["Mini Jall"]},{"day":"23", "name": ["Tom Smith","Michael Bird"]}]
i looked around, but i don't find a solution for that.我环顾四周,但我没有找到解决方案。 i checked this:
我检查了这个:
for(var i = 0; i < json.length; i++) {
var obj = json[i];
console.log(obj.id);
}
but didn't match.但不匹配。 Who can help?
谁能帮忙?
attachment 1: my code in the node_helper.js:附件1:我在node_helper.js中的代码:
start() {
console.log("Starting module helper: " + this.name);
// console.log("Pfad zur csv-Datei: " + this.path + "/data/birthdays.csv");
const csvFilePath = this.path + '/data/birthdays.csv';
csv()
.fromFile(csvFilePath)
.then((jsonObj)=>{
birthdaysArray = JSON.stringify(jsonObj);
console.log("birthdaysArray: " + birthdaysArray);
var result = Object.entries(birthdaysArray.reduce((a, {birth, name}) => {
const day = +birth.split('.')[0];
a[day] = [...(a[day] || []), name];
return a
}, {})).map(([day, name]) => ({day, name})).sort((a, b) => +a.day - b.day)
console.log("sorted birthdays : " + result);
})
}
=> output console.log: => output 控制台日志:
Unhandled rejection TypeError: birthdaysArray.reduce is not a function
at /home/dirk/MagicMirror/modules/perlchamp/node_helper.js:27:47
at Object.onfulfilled (/home/dirk/MagicMirror/node_modules/csvtojson/v2/Converter.js:112:33)
at Result.endProcess (/home/dirk/MagicMirror/node_modules/csvtojson/v2/Result.js:83:50)
at Converter.processEnd (/home/dirk/MagicMirror/node_modules/csvtojson/v2/Converter.js:179:21)
at /home/dirk/MagicMirror/node_modules/csvtojson/v2/Converter.js:172:19
at tryCatcher (/home/dirk/MagicMirror/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/dirk/MagicMirror/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/home/dirk/MagicMirror/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/home/dirk/MagicMirror/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/home/dirk/MagicMirror/node_modules/bluebird/js/release/promise.js:729:18)
at _drainQueueStep (/home/dirk/MagicMirror/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/home/dirk/MagicMirror/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/home/dirk/MagicMirror/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/home/dirk/MagicMirror/node_modules/bluebird/js/release/async.js:15:14)
at processImmediate (internal/timers.js:439:21)
so, what can i do?那么,我该怎么办?
attachment 2: first I wanted to filter the string by month:附件2:首先我想按月过滤字符串:
var today_month = moment().format("MM")
var monthList = [];
for(let prop in jsonObj) {
if (jsonObj[prop]["birth"].split(".")[1] == today_month) {
//console.log("fifth: ", jsonObj[prop]);
monthList += jsonObj[prop];
}
}
console.log("monthList: ", monthList);
...and then apply the code (green hook, the second of them) to it. ...然后将代码(绿色钩子,第二个)应用到它。 unfortunately does not work as I had imagined can you do this now in one go?
不幸的是不能像我想象的那样工作你现在可以在一个 go 中做到这一点吗? So filter from the annual list of birthdays by the current month, and then display these entries as I mentioned above.
因此,按当月从年度生日列表中过滤,然后按我上面提到的那样显示这些条目。
Now that you changed the expected result - it's a little cleaner现在你改变了预期的结果——它更干净了
var data = [{ "birth": "23.04.1988", "name": "Tom Smith" }, { "birth": "15.04.2010", "name": "Mini Jall" }, { "birth": "23.04.2001", "name": "Michael Bird" }, { "birth": "17.05.2001", "name": "May Gibbs" }, { "birth": "04.05.2001", "name": "May The Force be with you" }, { "birth": "17.05.2001", "name": "Jenny May" } ]; var currentMonth = new Date().toLocaleDateString('en', {month:'2-digit'}); var result = Object.entries(data.filter(({birth}) => birth.split('.')[1] === currentMonth).reduce((a, {birth, name}) => { const day = +birth.split('.')[0]; a[day] = [...(a[day] || []), name]; return a }, {}) ).map(([day, name]) => ({day, name})).sort((a, b) => +a.day - b.day); console.log(result);
The goal is to create an Array of Object s who's structure is [{ day: String, name: [String] }, …]
.目标是创建一个Object的数组,其结构为
[{ day: String, name: [String] }, …]
。 Noting that repeated days will be grouped into the same Object who's day indicates the grouping.请注意,重复的日期将被分组到相同的Object中,日期指示分组。
The input data is an Array who's format is [{ birth: String, name: String }, …]
.输入数据是一个数组,其格式为
[{ birth: String, name: String }, …]
。
"25.04.1988"
).
"25.04.1988"
)中提取一个有意义的日期。
To transform this String you can use a regular expression , with a callback parameter that orders the date in ISO-8601 Date format which the ECMA standard stipulates that Date
must support in its construction.要转换此字符串,您可以使用带有回调参数的正则表达式,该参数以ISO-8601 日期格式对日期进行排序, ECMA标准规定
Date
在其构造中必须支持。 Note also that Date expects its input to be in UTC time, ie, it is ignorant of timezone.另请注意, Date期望其输入为 UTC 时间,即它不知道时区。
Such a construction may look like这样的结构可能看起来像
const input = new Date('23.04.1988'.replace(/^(\d+)[^\d+](\d+)[^\d+](\d+)$/, (...backRefs) => { return `${backRefs[3]}-${backRefs[2]}-${backRefs[1]}`; }));
The ECMAScript syntax (which Node.js implements) for declaring a regular expression literal is utilised here: /RegularExpressionBody/RegularExpressionFlags
, where the flags are empty and the expression body is ^(\d+)[^\d+](\d+)[^\d+](\d+)$
.此处使用了用于声明正则表达式文字的 ECMAScript 语法( Node.js实现):
/RegularExpressionBody/RegularExpressionFlags
,其中标志为空,表达式主体为^(\d+)[^\d+](\d+)[^\d+](\d+)$
。
This regular-expression does not match a valid date, but instead any construction of three series of numerals (\d+)
, broken by non-numeric characters [^\d+]
which constitutes an entire String .此正则表达式与有效日期不匹配,而是由三个数字系列
(\d+)
的任何构造匹配,由构成整个String的非数字字符[^\d+]
打破。 It then reconstructs them using back-references in the order of 3-2-1
with dashes separating them as per the ISO-8601 Date 's format.然后,它使用
3-2-1
顺序的反向引用重建它们,并按照ISO-8601 Date的格式用破折号分隔它们。
That is the part `${backRefs[3]}-${backRefs[2]}-${backRefs[1]}`
, which utilises Template Literals often referred to incorrectly as template string s.那就是
`${backRefs[3]}-${backRefs[2]}-${backRefs[1]}`
部分,它利用了经常被错误地称为模板字符串的模板文字。
Constructing a Date Object from this new variable const input
will work, but it's toString()
method will return the String "Invalid Date"
if it is indeed, invalid.从这个新的变量
const input
构造一个Date Object是可行的,但是如果它确实是无效的,它的toString()
方法将返回字符串"Invalid Date"
。 If the input date does not match the regular expression, such that a back-reference indexes a capture group that doesn't capture;如果输入日期与正则表达式不匹配,则反向引用索引未捕获的捕获组; then the type of the constructed Date is
undefined
as it will be constructed with invalid inputs.那么构造的Date的类型是
undefined
的,因为它将使用无效的输入构造。 This particular result could be used to aggregate invalid birth-dates.此特定结果可用于汇总无效的出生日期。
const input = [{ "birth": "23.04.1988", "name": "Tom Smith" }, { "birth": "15.04.2010", "name": "Mini Jall" }, { "birth": "23.04.2001", "name":"Michael Bird" }];
Let input
be your input Array of Object s.让
input
成为Object的输入数组。
The Array Object provides a Function called map
on its prototype that you can use on input
since it is an Array .阵列Object在其原型上提供了一个名为map的
map
,您可以在input
上使用它,因为它是一个阵列。 This Function 's specification is Array.prototype.map(callbackFn[, thisArg])
.这个Function的规范是
Array.prototype.map(callbackFn[, thisArg])
。 It is called once for each element that exists in the Array which is the object being traversed .它为数组中存在的每个元素调用一次,即被遍历的 object 。 The returned value of the callback replaces the original object in a temporary Array which is returned by
map
upon completion.回调的返回值替换了临时数组中的原始 object,该临时数组由
map
在完成时返回。 In other words, you can map your Array into a new structure, by returning that structure from the callback using each element's properties as you iterate.换句话说,您可以通过在迭代时使用每个元素的属性从回调中返回该结构来将您的数组map 转换为新结构。 Note that the argument
thisArg
is a context under which the map
Function is invoked, and that if you call input.map
then the context is inherited as input
and so, thisArg
is only optional.请注意,参数
thisArg
是调用map
Function的上下文,并且如果您调用input.map
则只有上下文作为input
继承,因此thisArg
是可选的。
Such an invocation would look like input.map(argumentsList)
where argumentsList is a list that contains only a callback Function .这样的调用看起来像
input.map(argumentsList)
其中argumentsList是一个仅包含回调Function的列表。 The callback takes up to three parameters: currentValue, currentInndex, and the object being traversed.回调最多需要三个参数:currentValue、currentIndex 和正在遍历的 object。
So your callback should take the form of所以你的回调应该采取以下形式
(curr, idx, arr) => { return…; } // or function (curr, idx, arr) { return…; }
In this callback, you want to transform the birth
parameter to a day , so using the discussed methodology you would do something like在此回调中,您希望将
birth
参数转换为day ,因此使用所讨论的方法,您可以执行类似的操作
let dateCB = ({ birth, name }, idx, arr) => { const dateString = birth.replace(/^(\d+)[^\d+](\d+)[^\d+](\d+)$/, (...backRefs) => { return `${backRefs[3]}-${backRefs[2]}-${backRefs[1]}`; }); const date = new Date(dateString); const retObj = { day: date.getDate(), month: date.getUTCMonth() + 1, name }; Object.defineProperty(retObj, 'month', { enumerable: false }); return retObj; };
We add 1
to the month because getUTCMonth
returns a zero indexed month of the year.我们将
1
添加到月份,因为getUTCMonth
返回一年中索引为零的月份。 Also we define the property month
to be non-enumerable as we don't want it to show up in the result object.此外,我们将属性
month
定义为不可枚举,因为我们不希望它出现在结果 object 中。 Note also that the curr
from earlier, is being destructured in { birth, name }
and re-structured in { day: date.getDate(), month: date.getUTCMonth() + 1, name }
.另请注意,之前的
curr
在{ birth, name }
中被解构并在{ day: date.getDate(), month: date.getUTCMonth() + 1, name }
中重新构建。 Destructuring assignment allows you to reduce an Object 's properties into property names and in the argumentsList it declares those properties as variables in the scope of the arrow function.解构赋值允许您将Object的属性减少为属性名称,并在argumentsList中将这些属性声明为箭头 ZC1C425268E68385D1AB4ZZC17A94F 的 scope 中的变量。 This is actually a shorthand for
{ birth: birth, name: name }
since they have the same identifier as the properties of the input object curr
.这实际上是
{ birth: birth, name: name }
的简写,因为它们具有与输入 object curr
的属性相同的标识符。
[ { "day":23, "month": 4, "name": "Tom Smith" }, { "day": 15, "month": 4, "name": "Mini Jall" }, { "day": 23, "month": 4, "name": "Michael Bird" } ]
Except that the month
properties will not be enumerable.除了不能枚举
month
属性。
You want to collate these Object s such that the String name
is instead an Array
of all name
s who's parent Object shares identical day
and month
properties with other Object members of the Array .您想要整理这些Object s,以便String
name
是所有name
s 的Array
,其父Object与Array的其他Z497031794414A552435F9015B成员共享相同的day
和month
属性。
So we will look to using Array.prototype.reduce
which is defined as Array.prototype.reduce(callbackfn[, initialValue])
.所以我们将考虑使用定义为
Array.prototype.reduce
Array.prototype.reduce(callbackfn[, initialValue])
的 Array.prototype.reduce。 The callback Function takes up to four parameters: previousValue, currentValue, currentIndex, and the object being traversed.回调Function最多需要四个参数:previousValue、currentValue、currentIndex 和正在遍历的 object。 If you provide
initialValue
then reduce
iterates beginning at the first element, and the initialValue
is provided to the callback as previousValue
.如果您提供
initialValue
,则reduce
从第一个元素开始迭代,并将initialValue
作为previousValue
提供给回调。 However if you omit initialValue
then reduce
iterates beginning at the second element providing the first element as previousValue
.但是,如果您省略
initialValue
,则reduce
从第二个元素开始的迭代,提供第一个元素作为previousValue
。 What you return from the callback is then passed to the next iteration as its previousValue
.然后,您从回调返回的内容将作为其
previousValue
传递给下一次迭代。
We'll also be using Array.prototype.findIndex
which is defined as Array.prototype.findIndex(predicate[, thisArg ])
.我们还将使用定义为
Array.prototype.findIndex
Array.prototype.findIndex(predicate[, thisArg ])
的 Array.prototype.findIndex。 The predicate Function takes up to three parameters and should return a boolean coercible result (such as 1
, 0
, true
, false
, undefined
, etc).谓词Function最多需要三个参数,并且应该返回 boolean 强制结果(例如
1
、 0
、 true
、 false
、 undefined
等)。 findIndex
will return -1
if no predicate returns true
, or it will return the index it reached when the first predicate does.如果没有谓词返回
true
, findIndex
将返回-1
,否则它将返回它在第一个谓词返回时达到的索引。
We can use this to find out if an array contains a matching day
and month
for an iteration of the reducer.我们可以使用它来确定数组是否包含匹配的
day
和month
,以用于 reducer 的迭代。
({ day: tDay, month: tMonth, name: tName }) => { return tDay === … && tMonth === …; }
We want to construct a new Array output and we will iterate over the input using reduce
, constructing the output as we go.我们要构造一个新的数组output 并且我们将使用
reduce
遍历输入,构造 output 就像我们 go 一样。 For this reason, reduce will be called with an empty array as its optional second argument出于这个原因,reduce 将使用一个空数组作为其可选的第二个参数来调用
let reducer = (prev, { day, month, name }) => { if (prev.length === 0) { /// this is the first iteration, where prev is empty prev.push({ day, month, name: [name] }); } else { /// this is any other iteration, now we have to search `prev` let where = prev.findIndex(({ day: tDay, month: tMonth, name: tName }) => { return tDay === day && tMonth === month; }); if (where.== -1) { prev[where].name;push(name). } else { prev,push({ day, month: name; [name] }); } } return prev; }
And the invocation looks like调用看起来像
input.map(dateCB).reduce(reducer, []);
Array.prototype.sort
defined as Array.prototype.sort(comparefn)
.
Array.prototype.sort
定义为Array.prototype.sort(comparefn)
。
The comparefn
Function receives two arguments, x
and y
.
comparefn
Function接收两个 arguments, x
和y
。
The job of comparefn
is to describe how x
relates to y
.
comparefn
的工作是描述x
与y
的关系。
The sorter expects a negative Number returned from comparefn
if x < y
, zero if x == y
and positive if x > y
.
x < y
,则排序器期望从comparefn返回comparefn
,如果x == y
则返回零,如果x > y
则返回正数。
x
and y
are two members of the Array being sorted, and so since those members have the same structure you may destructure x
and y
as { day: xDay }, { day: yDay }
and return xDay - yDay
for a sufficient result.
x
和y
是要排序的Array的两个成员,因此由于这些成员具有相同的结构,您可以将x
和y
解构为{ day: xDay }, { day: yDay }
并返回xDay - yDay
以获得足够的结果。
cDay
which is just a String representation of the day
property.
cDay
,它只是day
属性的字符串表示形式。
I also implement the non-enumerable property on the final Object s in the Array and the sorter on the output.
const input = [{ "birth": "23.04.1988", "name": "Tom Smith" }, { "birth": "15.04.2010", "name": "Mini Jall" }, { "birth": "23.04.2001", "name":"Michael Bird" }]; const dateCB = ({ birth, name }, idx, arr) => { const dateString = birth.replace(/^(\d+)[^\d+](\d+)[^\d+](\d+)$/, (...backRefs) => { return `${backRefs[3]}-${backRefs[2]}-${backRefs[1]}`; }); const date = new Date(dateString); const retObj = { day: date.getDate(), month: date.getUTCMonth() + 1, name }; return retObj; }; const reducer = (prev, { day, month, name }) => { const cDay = day.toString(10); const retObj = { day: cDay, month, name: [name] }; Object.defineProperty(retObj, 'month', { enumerable: false }); if (prev.length === 0) { prev.push(retObj); } else { const where = prev.findIndex(({ day: tDay, month: tMonth, name: tName }) => { return tDay === cDay && tMonth === month; }); if (where.== -1) { prev[where].name;push(name). } else { prev;push(retObj); } } return prev; }: const sorter = ({ day, bDay }: { day; aDay }) => { return bDay - aDay; }. const output = input.map(dateCB),reduce(reducer. []);sort(sorter). console.log(JSON;stringify(output));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.