2 回答
TA贡献1816条经验 获得超6个赞
您可以为此使用递归函数。很难根据问题中的信息给出一个确切的例子,但例如:
function process(obj) {
// Loop through the values of the own properties of the object
for (const value of Object.values(obj)) {
// Is this the termination condition?
if (Array.isArray(value)) { // <== A guess at the condition, adjust as needed
// We've reached the bottom
value.sort((x, y) => x.date.localeCompare(y.date)); // <== Note correction, you can't just return the result of `>`
} else {
// Not the termination, recurse
process(value);
}
}
}
使用猜测数据的实时示例:
function process(obj) {
// Loop through the values of the own properties of the object
for (const value of Object.values(obj)) {
// Is this the termination condition?
if (Array.isArray(value)) { // <== A guess at the condition, adjust as needed
// We've reached the bottom
value.sort((x, y) => x.date.localeCompare(y.date)); // <== Note correction, you can't just return the result of `>`
} else {
// Not the termination, recurse
process(value);
}
}
}
const objRes = {
group1: {
type1: {
name1: {
tenor1: [
{date: '2019-12-23', value: 35},
{date: '2019-12-25', value: 32},
{date: '2019-12-24', value: 30},
]
},
name2 :[]
},
type2: {}
},
group2: {}
};
process(objRes);
console.log(JSON.stringify(objRes, null, 4));
.as-console-wrapper {
max-height: 100% !important;
}
一些注意事项:
您可以通过使用来避免
for-in
/hasOwnProperty
组合Object.values
。您可以使用 遍历这些值
for-of
。必须有一些终止条件告诉函数何时到达“底部”。在那个例子中,我使用了
Array.isArray
因为你在最后一级排序。Array.prototype.sort
直接修改数组,不需要使用它的返回值。您传递给的函数
sort
必须返回负数、0 或正数,而不是布尔值(更多信息请点击此处)。由于您的date
值在yyyy-MM-dd
形式上似乎是字符串,因此您可以使用localeCompare
它(因为在这种格式中,字典比较也是日期比较)。
TA贡献1776条经验 获得超12个赞
这个替代 TJ Crowder 的答案采用了那里提到的几个决策点,并使它们显式函数调用。
const process = (test, transform, data) =>
typeof data == "object"
? ( Array .isArray (data)
? (xs) => xs .map (([_, x]) => x)
: Object .fromEntries
) ( Object .entries (data) .map (([k, v]) =>
[k, test (k, v) ? transform (v) : process (test, transform, v)]
))
: data
它接受两个函数以及您的数据对象。第一个是测试您是否遇到了要按摩的嵌套值。所以我们可以想象像(k, v) => k .startsWith ('tenor')或 之类的东西(k, v) => Array .isArray (v)。第二个函数接受该条目处的值并返回一个更新的值,可能是(v) => v . sort((a, b) => a .date .localeCompare (b .date))。
(注意:您的排序调用是有问题的。不要使用.sort ((a, b) => a < b),它返回一个布尔值,然后被强制转换为 a0或 a 1,而适当的比较器应该返回-1when a < b。如果您可以与 进行比较<,那么这应该始终有效(a, b) => a < b ? -1 : a > b ? 1 : 0。我不”不知道是否有比使用 .sort((a,b) => a>b) 对数组进行排序更完整的问题。为什么?。)
您可以在此代码段中看到它的运行情况:
const process = (test, transform, data) =>
typeof data == "object"
? ( Array .isArray (data)
? (xs) => xs .map (([_, x]) => x)
: Object .fromEntries
) ( Object .entries (data) .map (([k, v]) =>
[k, test (k, v) ? transform (v) : process (test, transform, v)]
))
: data
const dateSort = (xs) => xs .slice (0) .sort ((a, b) => a .date .localeCompare (b .date))
const objRes = {
group1: {
type1: {
name1: {
tenor1: [
{date: '2019-12-23', value: 35},
{date: '2019-12-25', value: 32},
{date: '2019-12-24', value: 30},
]
},
name2: []
},
type2: {}
},
group2: {
type3: [
{date: '2020-01-03', value: 42},
{date: '2019-01-01', value: 43},
{date: '2019-01-02', value: 44},
]
}
};
// This one only sorts the first group of dates
console .log (
process (
(k, v) => k .startsWith ('tenor'),
dateSort,
objRes
)
)
// This one sorts both groups
console .log (
process (
(k, v) => Array .isArray (v),
dateSort,
objRes
)
)
代码有点密集。最外层条件仅在数据是对象时才应用我们的处理,如果不是则完整返回,如果是则执行以下处理:
我们首先使用Object.entries将我们的对象转换为名称-值对,然后通过测试每一对来映射该对象,看看我们是否遇到了应该转换的东西,并返回转换后的值或对值进行递归的结果。
也许最棘手的一点是:
( Array .isArray (data)
? (xs) => xs .map (([_, x]) => x)
: Object .fromEntries
)
在这里,我们只选择一个函数应用到转换后的对上,将其重新变成一个整体。如果它是一个数组,我们跳过键并返回一个值数组。如果不是,我们就用它们Object.fromEntries来创建一个对象。如果Object.entries是不是在你的环境中使用,很容易垫片。
添加回答
举报