Javascript 根据多个值将数组与其他数组组合

Javascript Combine Array by Other Array Based on Multiple Values

我有一个名为 p 的数组,它看起来像:

[
  {
    "Day": "Monday",
    "data": [
      "chest",
      "triceps",
      "shoulders"
    ]
  },
  {
    "Day": "Tuesday",
    "data": [
      "back",
      "biceps"
    ]
  },
  {
    "Day": "Thursday",
    "data": [
      "legs"
    ]
  }
]

我还有另一个数组,program 看起来像:(略读)

[
  {
    "target": "biceps",
    "data": [
      {
        "name": "barbell alternate biceps curl",
        "target": "biceps"
      },
      {
        "name": "barbell lying preacher curl",
        "target": "biceps"
      }
    ]
  },
  {
    "target": "triceps",
    "data": [
      {
        "name": "barbell incline reverse-grip press",
        "target": "triceps"
      },
      {
        "name": "barbell lying extension",
        "target": "triceps"
      }
    ]
  }
]

我需要程序来对 p.data 拥有的肌肉群进行分组。它应该看起来像:

[
      {
        "target": "chest tricep shoulder",
        "data": [
          {
            "name": "chest exercise",
            "target": "chest"
          },

          {
            "name": "tricep exercise",
            "target": "tricep"
          },
          {
            "name": "shoulder exercise",
            "target": "shoulder"
          },
        ]
      },

      {
        "target": "back biceps",
        "data": [
          {
            "name": "back exercise",
            "target": "back"
          },

          {
            "name": "bicep exercise",
            "target": "bicep"
          },
        ]
      },
]

我试过这个(基于数组排序),但不是正确的尝试:

function mapOrder(array, order, property) {
  let ordered = [], unordered = [];

  // Iterate over each item in the supplied array of objects, separating ordered and unordered objects into their own arrays.
  array.forEach((item) => {
  if (order.indexOf(item[property]) === -1) {
      unordered.push(item);
  } else {
      ordered.push(item);
  }
  });

  // Sort the ordered array.
  ordered.sort((a, b) => {
  a = a[property], b = b[property];

  if (order.indexOf(a) < order.indexOf(b)) {
      return -1;
  } else {
      return 1;
  }
  });

  // Sort the unordered array.
  unordered.sort((a, b) => {
  a = a[property], b = b[property];

  if (a < b) {
      return -1;
  } else if (a > b) {
      return 1;
  } else {
      return 0;
  }
  });

  // Append the sorted, non-ordered array to the sorted, ordered array.
  ordered.push(...unordered);

  return ordered;
}

您可以使用以下实现:

const programs = [
  {
    target: "biceps",
    data: [
      {
        name: "barbell alternate biceps curl",
        target: "biceps",
      },
      {
        name: "barbell lying preacher curl",
        target: "biceps",
      },
    ],
  },
  {
    target: "triceps",
    data: [
      {
        name: "barbell incline reverse-grip press",
        target: "triceps",
      },
      {
        name: "barbell lying extension",
        target: "triceps",
      },
    ],
  },
];

// creates a Map which maps
// muscle => Array of exercises
const lookupTable = programs.reduce(
  (map, { target, data }) => (map.set(target, data), map),
  new Map()
);

const p = [
  {
    Day: "Monday",
    data: ["chest", "triceps", "shoulders"],
  },
  {
    Day: "Tuesday",
    data: ["back", "biceps"],
  },
  {
    Day: "Thursday",
    data: ["legs"],
  },
];

// for each day map the respective exercises
const result = p.map((day) => ({
  // join together the muscles to a muscle group
  target: day.data.join(" "),
  // for each muscle get the respective exercises and put them in a list
  // if a muscle does not exist (as here in this limited example) set some default value (please adjust as you please)
  data: day.data.flatMap(
    (muscle) =>
      lookupTable.get(muscle) || {
        name: `Muscle ${muscle} does not exist`,
        target: muscle,
      }
  ),
}));
console.log(JSON.stringify(result, null, 4));
.as-console-wrapper { max-height: 100% !important; top: 0; }

首先,我使用 Map 创建一个查找 table,这将允许在 O(1) 中进行快速查找,并将给定的肌肉映射到一组相应的练习,如下所示。

I use reduce() for this but that's not required. You could just create the Map beforehand and manually add the arrays within a loop over the array.

Map(2) {
  'biceps' => [
    { name: 'barbell alternate biceps curl', target: 'biceps' },
    { name: 'barbell lying preacher curl', target: 'biceps' }
  ],
  'triceps' => [
    { name: 'barbell incline reverse-grip press', target: 'triceps' },
    { name: 'barbell lying extension', target: 'triceps' }
  ]
}

然后我使用 map() and flatMap() 为每一天创建一个训练计划,其中包含当天所有指定肌肉的所有练习。 要为肌肉群创建字符串,我们可以 join() 肌肉数组。