如何根据另一个对象数组提供的属性对对象数组进行排序?

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; }