如何根据另一个对象数组提供的属性对对象数组进行排序?
How to sort an array of objects on the basis of properties which are provided by another array of objects?
我一直在努力根据数组中不存在的 属性 对对象数组进行排序。
我有我的第一个数组
const scores = [
{
"scoreDefinitionName": "_mo45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573564",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_sc45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573568",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_ua45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573572",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "KFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573576",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "LFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573580",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "dummy",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573584",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "Score",
"score": 0.32,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573588",
"globalId": null,
"version": 0
}
}
]
第二个数组就像
[
{
variableName: "KFT",
variable: "KFT",
sequence: 1,
variableDetail: {
displayName: ""
},
},
{
variableName: "LFT",
variable: "LFT",
sequence: 3,
variableDetail: {
displayName: ""
},
},
{
variableName: "Dummy",
variable: "dummy",
sequence: 2,
variableDetail: {
displayName: ""
}
}
];
所以基本上我想要做的是根据与第二个数组 varibles
中的对象匹配的对象的序列对第一个数组 scores
进行排序,当名称 属性比赛。
我发现的一个解决方法是首先将 variables
数组的 sequence
属性 推入 scores
数组,然后根据它进行排序
但我相信它可以进一步优化。还有其他方法可以使其更优化吗?
下面介绍的是实现所需 objective 的一种可能方法,其中 假设 scores
数组需要根据 sequence
prop 在 variables
数组上(而不是在填充 variables
数组的顺序上)。换句话说,所需的 sort-order 是 KFT、Dummy、LFT,这是根据 sequence
为 1、2、3;并且不是KFT, LFT, Dummy对应的sequence
是1, 3, 2.
代码段
// method to sort using custom logic (without mutating the input array)
const mySort = (arr, ord) => (
structuredClone(arr) // deep-clone to avoid mutating parameter array
.sort(
(
{scoreDefinitionName: sdA}, // de-structure to access "scoreDefinitionName"
{scoreDefinitionName: sdB} // of both 'a' and 'b'
) => {
if (sdA in ord && sdB in ord) { // if both "scoreDefinitionName"s are in variables
return ord[sdA] - ord[sdB] // use the "sequence number to sort
} else if (sdA in ord) { // else, if only 'a' is in 'variables' array
return -1;
} else if (sdB in ord) { // 'a' is not but 'b' is in 'variables' array
return 1;
} else return ( // both 'a' and 'b' are not in the array
sdA < sdB ? -1 : 1 // sort using the "scoreDefinitionName"
);
}
) // implicit return of the "sort"-ed array
);
const scores = [
{
"scoreDefinitionName": "_mo45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573564",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_sc45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573568",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_ua45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573572",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "KFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573576",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "LFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573580",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "dummy",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573584",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "Score",
"score": 0.32,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573588",
"globalId": null,
"version": 0
}
}
];
const variables = [
{
variableName: "KFT",
variable: "KFT",
sequence: 1,
variableDetail: {
displayName: ""
},
},
{
variableName: "LFT",
variable: "LFT",
sequence: 3,
variableDetail: {
displayName: ""
},
},
{
variableName: "Dummy",
variable: "dummy",
sequence: 2,
variableDetail: {
displayName: ""
}
}
];
// invoke the custom sort method
// transform 'variables' array into an object
// with key-value pair as 'variable': 'sequence'
// This helps in sorting using the sequence
console.log(
'sorting scores arr using ordering from variables array...\n',
mySort(
scores,
Object.fromEntries(
variables.map(
({ variable, sequence }) => [variable, sequence]
)
)
)
);
.as-console-wrapper { max-height: 100% !important; top: 0 }
说明
在上面的代码段中添加了内联评论。
比较函数的实现方式是,它首先根据预定义优先级条目的绑定映射比较 score-items,其中 key
是从 variable
值中检索的,并且并且优先级 value
是从第二个数组项的 sequence
值中检索的,并且在第二步中根据升序将 score-items 与它们的 scoreDefinitionName
进行比较。
function compareScoreItemsByDefinitionNameAndBoundPrecedence(a, b) {
const precedenceLookup = this;
const aName = a.scoreDefinitionName;
const bName = b.scoreDefinitionName;
const aPrecedence = precedenceLookup.get(aName) ?? null;
const bPrecedence = precedenceLookup.get(bName) ?? null;
return (
(aPrecedence === null && bPrecedence !== null && 1) ||
(aPrecedence !== null && bPrecedence === null && -1) ||
(aPrecedence !== null && bPrecedence !== null && aPrecedence - bPrecedence) ||
// ascending name order if no predefined precedence
// is available or precedence comparison value was zero.
aName.localeCompare(bName)
);
}
const namePrecedence = [{
variableName: "KFT",
variable: "KFT",
sequence: 1,
variableDetail: {
displayName: ""
},
}, {
variableName: "LFT",
variable: "LFT",
sequence: 3,
variableDetail: {
displayName: ""
},
}, {
variableName: "Dummy",
variable: "dummy",
sequence: 2,
variableDetail: {
displayName: ""
}
}];
const scores = [{
"scoreDefinitionName": "_mo45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573564",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "_sc45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573568",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "_ua45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573572",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "KFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573576",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "LFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573580",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "dummy",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573584",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "Score",
"score": 0.32,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573588",
"globalId": null,
"version": 0
}
}];
console.log(
'... key value tuple of the to be created and bound precedence map ...',
namePrecedence
.map(({ variable, sequence }) => [variable, sequence])
);
scores.sort(
compareScoreItemsByDefinitionNameAndBoundPrecedence
.bind(
new Map(
namePrecedence
.map(({ variable, sequence }) => [variable, sequence])
)
)
);
console.log({ scores });
.as-console-wrapper { min-height: 100%!important; top: 0; }
我一直在努力根据数组中不存在的 属性 对对象数组进行排序。 我有我的第一个数组
const scores = [
{
"scoreDefinitionName": "_mo45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573564",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_sc45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573568",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_ua45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573572",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "KFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573576",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "LFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573580",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "dummy",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573584",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "Score",
"score": 0.32,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573588",
"globalId": null,
"version": 0
}
}
]
第二个数组就像
[
{
variableName: "KFT",
variable: "KFT",
sequence: 1,
variableDetail: {
displayName: ""
},
},
{
variableName: "LFT",
variable: "LFT",
sequence: 3,
variableDetail: {
displayName: ""
},
},
{
variableName: "Dummy",
variable: "dummy",
sequence: 2,
variableDetail: {
displayName: ""
}
}
];
所以基本上我想要做的是根据与第二个数组 varibles
中的对象匹配的对象的序列对第一个数组 scores
进行排序,当名称 属性比赛。
我发现的一个解决方法是首先将 variables
数组的 sequence
属性 推入 scores
数组,然后根据它进行排序
但我相信它可以进一步优化。还有其他方法可以使其更优化吗?
下面介绍的是实现所需 objective 的一种可能方法,其中 假设 scores
数组需要根据 sequence
prop 在 variables
数组上(而不是在填充 variables
数组的顺序上)。换句话说,所需的 sort-order 是 KFT、Dummy、LFT,这是根据 sequence
为 1、2、3;并且不是KFT, LFT, Dummy对应的sequence
是1, 3, 2.
代码段
// method to sort using custom logic (without mutating the input array)
const mySort = (arr, ord) => (
structuredClone(arr) // deep-clone to avoid mutating parameter array
.sort(
(
{scoreDefinitionName: sdA}, // de-structure to access "scoreDefinitionName"
{scoreDefinitionName: sdB} // of both 'a' and 'b'
) => {
if (sdA in ord && sdB in ord) { // if both "scoreDefinitionName"s are in variables
return ord[sdA] - ord[sdB] // use the "sequence number to sort
} else if (sdA in ord) { // else, if only 'a' is in 'variables' array
return -1;
} else if (sdB in ord) { // 'a' is not but 'b' is in 'variables' array
return 1;
} else return ( // both 'a' and 'b' are not in the array
sdA < sdB ? -1 : 1 // sort using the "scoreDefinitionName"
);
}
) // implicit return of the "sort"-ed array
);
const scores = [
{
"scoreDefinitionName": "_mo45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573564",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_sc45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573568",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "_ua45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573572",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "KFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573576",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "LFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573580",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "dummy",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573584",
"globalId": null,
"version": 0
}
},
{
"scoreDefinitionName": "Score",
"score": 0.32,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573588",
"globalId": null,
"version": 0
}
}
];
const variables = [
{
variableName: "KFT",
variable: "KFT",
sequence: 1,
variableDetail: {
displayName: ""
},
},
{
variableName: "LFT",
variable: "LFT",
sequence: 3,
variableDetail: {
displayName: ""
},
},
{
variableName: "Dummy",
variable: "dummy",
sequence: 2,
variableDetail: {
displayName: ""
}
}
];
// invoke the custom sort method
// transform 'variables' array into an object
// with key-value pair as 'variable': 'sequence'
// This helps in sorting using the sequence
console.log(
'sorting scores arr using ordering from variables array...\n',
mySort(
scores,
Object.fromEntries(
variables.map(
({ variable, sequence }) => [variable, sequence]
)
)
)
);
.as-console-wrapper { max-height: 100% !important; top: 0 }
说明
在上面的代码段中添加了内联评论。
比较函数的实现方式是,它首先根据预定义优先级条目的绑定映射比较 score-items,其中 key
是从 variable
值中检索的,并且并且优先级 value
是从第二个数组项的 sequence
值中检索的,并且在第二步中根据升序将 score-items 与它们的 scoreDefinitionName
进行比较。
function compareScoreItemsByDefinitionNameAndBoundPrecedence(a, b) {
const precedenceLookup = this;
const aName = a.scoreDefinitionName;
const bName = b.scoreDefinitionName;
const aPrecedence = precedenceLookup.get(aName) ?? null;
const bPrecedence = precedenceLookup.get(bName) ?? null;
return (
(aPrecedence === null && bPrecedence !== null && 1) ||
(aPrecedence !== null && bPrecedence === null && -1) ||
(aPrecedence !== null && bPrecedence !== null && aPrecedence - bPrecedence) ||
// ascending name order if no predefined precedence
// is available or precedence comparison value was zero.
aName.localeCompare(bName)
);
}
const namePrecedence = [{
variableName: "KFT",
variable: "KFT",
sequence: 1,
variableDetail: {
displayName: ""
},
}, {
variableName: "LFT",
variable: "LFT",
sequence: 3,
variableDetail: {
displayName: ""
},
}, {
variableName: "Dummy",
variable: "dummy",
sequence: 2,
variableDetail: {
displayName: ""
}
}];
const scores = [{
"scoreDefinitionName": "_mo45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573564",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "_sc45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573568",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "_ua45",
"score": 0,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573572",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "KFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573576",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "LFT",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573580",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "dummy",
"score": 1,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573584",
"globalId": null,
"version": 0
}
}, {
"scoreDefinitionName": "Score",
"score": 0.32,
"scoreDefinitionId": {
"objectType": "ScoreDefinition",
"idValue": "573588",
"globalId": null,
"version": 0
}
}];
console.log(
'... key value tuple of the to be created and bound precedence map ...',
namePrecedence
.map(({ variable, sequence }) => [variable, sequence])
);
scores.sort(
compareScoreItemsByDefinitionNameAndBoundPrecedence
.bind(
new Map(
namePrecedence
.map(({ variable, sequence }) => [variable, sequence])
)
)
);
console.log({ scores });
.as-console-wrapper { min-height: 100%!important; top: 0; }