我有一个特别具有挑战性的数据结构(我不控制),在该结构中,我需要基于嵌套数组和对象的组合来查找最新的对象,而沿途的某些属性是可选的。到目前为止,我已经设法过滤掉了可选属性的确存在的位置,但是说服javascript将日期拉长,以便我可以比较它们以找到最新的属性,这是充满挑战的。
这是数据结构:
const data = {
"objects": [
{
"id": "id1",
"code": "code1",
"props": [
{
"foos": [
{
"itemId": "theItem",
"fooDate": "2018-03-01T10:00:00.000Z"
}
]
}
]
},
{
"id": "id2",
"code": "code2",
"props": [
{
"bar": {
"itemId": "theItem",
"barDate": "2018-03-06T22:00:00.000Z"
}
}
]
},
{
"id": "id3",
"code": "code3",
"props": [
{
"foos": [
{
"itemId": "someOtherItem",
"fooDate": "2018-01-23T06:00:00.000Z"
},
{
"itemId": "theItem",
"fooDate": "2018-03-04T18:00:00.000Z"
}
]
}
]
}
]
}
const searchItem = "theItem";
const foosOnly = data.objects.filter(obj => obj.props.find(prop => prop.foos && prop.foos.find(foo => foo.itemId === searchItem)));
我要查找的是对象“ theItem”中最新的fooDate
对象,以便可以对对象的某些顶级属性进行操作,例如id
或{ {1}}。在此示例中,尽管“ id3”也具有较旧的code
,但我希望“ id3”是最新的。
我已经设法通过过滤器和查找来删除不包含fooDate
的对象,但是在foo
之间进行比较时,我很难对fooDate
进行操作,因此我可以找到最新的foos
。
答案 0 :(得分:1)
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="surveyApp" ng-controller="surveyCtrl">
<div ng-repeat="questionSet in questionSet">
<div ng-if="question_index == $index">
<div ng-repeat="onePageQuestions in questionSet.onePageQuestions">
<div ng-repeat="question in onePageQuestions.question">
{{question.description}}
<form action="">
<div ng-repeat="options in question.options">
<input ng-change="saveAnswers(question,options.answer)" type="radio" name="gender" ng-model="$parent.answer" ng-value="options.answer"> {{options.answer}}
</div>
</form>
</div>
</div>
</div>
</div>
<hr>
<button ng-click="next()">Next</button>
<button ng-click="submitAnswers()"> Submit</button>
的格式意味着您可以按字典顺序进行比较。寻找fooDate
只是意味着要进行大量的保护和循环操作:
fooDate
实时示例:
let latest = null;
let latestDate = null;
for (const item of data.objects) {
if (Array.isArray(item.props)) {
for (const prop of item.props) {
if (prop.foo) {
for (const {fooDate} of prop.foo) {
if (fooDate && (!latestDate || fooDate > latestDate)) {
latest = item;
latestDate = fooDate;
}
}
}
}
}
}
答案 1 :(得分:1)
我开始沿着导航对象层次结构的路线前进,但是似乎有太多的未知数。因此,如果您只是对名为fooDate
的属性感到好奇,则可以使用以下解决方案遍历对象,对每个对象进行字符串化,然后使用正则表达式获取日期:
let latest = null;
data.objects.forEach(obj => {
const json = JSON.stringify(obj);
const regex = new RegExp(/^.+"fooDate":"(.+)".+$/);
const match = json.match(regex);
if (match && match.length > 1) {
const [first, ...results] = match;
results.forEach(result => {
const timestamp = new Date(result).valueOf();
if (!latest || latest.timestamp < timestamp) {
latest = { obj, timestamp };
}
});
}
});
答案 2 :(得分:0)
下面的代码应该可以帮助您实现所需的目标。如果可行,我也会添加评论。
const data={"objects":[{"id":"id1","code":"code1","props":[{"foos":[{"itemId":"theItem","fooDate":"2018-03-01T10:00:00.000Z"}]}]},{"id":"id2","code":"code2","props":[{"bar":{"itemId":"theItem","barDate":"2018-03-06T22:00:00.000Z"}}]},{"id":"id3","code":"code3","props":[{"foos":[{"itemId":"someOtherItem","fooDate":"2018-01-23T06:00:00.000Z"},{"itemId":"theItem","fooDate":"2018-03-04T18:00:00.000Z"}]}]}]};
const list = data.objects;
const desiredObject = list.sort((itemA, itemB) => {
let itemAFoo = itemA.props.reduce((list, prop) => {return list.concat(prop.foos || [])}, []).sort((a, b) => a.fooDate - b.fooDate).pop() || {fooDate: 0};
let itemBFoo = itemA.props.reduce((list, prop) => {return list.concat(prop.foos || [])}, []).sort((a, b) => a.fooDate - b.fooDate).pop() || {fooDate: 0};
return itemAFoo.fooDate - itemBFoo.fooDate;
}).pop();
desiredItemId = desiredObject.props.reduce((list, prop) => {return list.concat(prop.foos || [])}, []).pop().itemId;
console.log('desiredObject:', desiredObject);
console.log('desiredItemId:', desiredItemId);
答案 3 :(得分:0)
以下是一些我认为可以解决您问题的代码。该方法的目的是创建一个新的类型的数据结构
{
id: string;
itemId: string;
date: Date;
}
之后,您可以简单地进行过滤/排序和搜索。因此,让我们看看如何创建以上数据。
类似的东西
const intermediateData = [];
function findItemIdAndDateRecursively(id, object) {
Object.keys(object).forEach((key) => {
if(key === 'itemId') {
let date;
for(let i in object) {
if (isUTCString(object[i])) {
date = object[i];
}
}
intermediateData.push({id: id, itemId: object.itemId, date: date})
} else if (typeof object[key] === 'object' || typeof object[key] === 'array') {
findItemIdAndDateRecursively(id, object[key]);
}
})
}
array.forEach(item => {
findItemIdAndDateRecursively(item.id, item);
})
其中isUTCString应该用来查找字符串是否为日期字符串。您可能必须根据获取的数据类型编写该实用程序功能。
答案 4 :(得分:-1)
您可以编写一个接收对象结束的函数,每次返回fooDate。 此功能可以执行诸如广度优先搜索之类的操作,以在对象中找到此键。
使用此功能后,可以遍历对象对象数组并保存找到的最新对象。