按另一个对象对对象(字符串)进行排序

时间:2018-11-12 19:23:24

标签: javascript arrays sorting object

我目前有一个看起来像这样的对象:

var data = {
    "a/a/something": "something/ehere"
    "a/b/somethingelse": "something/else/here",
    "a/b/somethingdifferent": "something/else/different",
    "a/c/somethingess": "something/else/somethingess",
    "b/a/somethingess": "something/else/somethingess",
    "b/a/somethingdifferent": "something/else/somethingess",
    "b/b/somethingdifferentasdasd": "something/else/somethingdifferent",
};

Object.keys当前分为3个元素,我只关心第一个[1]/[2]/[3]和第三个{}。

我当前正在运行一个foreach,该循环遍历所有对象键,但是我想按条件1和条件3对其进行排序。

我的循环:

Object.keys(data).forEach((dataID) => {
    register(dataID);
});

我的排序:

var sort = {
    "a": ["something", "somethingdifferent", "somethingelse"],
    "b": ["somethingess", "somethingdifferentasdasd"]
}

目标是,它可以检查键a/a/something是否在到达循环时应检查排序对象,然后再到达foreach。

forEach之前的预期结果

var data = {
    "a/a/something": "something/ehere"
    "a/b/somethingdifferent": "something/else/different",
    "a/b/somethingelse": "something/else/here",
    "a/c/somethingess": "something/else/somethingess",
    "b/a/somethingess": "something/else/somethingess",
    "b/b/somethingdifferentasdasd": "something/else/somethingdifferent",
    "b/a/somethingdifferent": "something/else/somethingess"
};

3 个答案:

答案 0 :(得分:1)

您可以执行以下操作:

const data = { "a/a/something": "something/ehere", "a/b/somethingelse": "something/else/here", "a/b/somethingdifferent": "something/else/different", "a/c/somethingess": "something/else/somethingess", "b/a/somethingess": "something/else/somethingess", "b/a/somethingdifferent": "something/else/somethingess", "b/b/somethingdifferentasdasd": "something/else/somethingdifferent", };
const sort = { "a": ["something", "somethingdifferent", "somethingelse"], "b": ["somethingess", "somethingdifferentasdasd"] }

const splitter = (s) => {
  let arr = s.split('/'), index = sort[arr[0]].indexOf(arr[2])
  return ({ k: arr[0], v: index < 0 ? Number.MAX_SAFE_INTEGER : index})
}
const sorter = (a, b) => splitter(a).v - splitter(b).v
const result = Object.entries(
    Object.keys(data)
    .reduce((r, c) => (r[splitter(c).k] = [...r[splitter(c).k] || [], c], r), {})
  )
  .map(([k, v]) => v.sort(sorter))
  .reduce((r, c) => r.concat(c))
  .reduce((r, c) => Object.assign(r, ({ [c]: data[c]})), {})

console.log(result)

想法是通过Object.keys获取密钥,然后按索引[0]将其分组,对它们进行排序,然后组成最终对象。

注意: Object props order is not guaranteed

  

对象是对象类型的成员。这是无序的   属性集合,每个属性都包含一个原始值,   对象或功能。存储在对象属性中的函数是   称为方法。

尽管SO控制台会在Chrome控制台中显示所需的顺序,但您不会获得相同的输出。仅供参考。

因此请牢记,如果您替换最后一行,而不是reduce,则执行map,因此最终结果是一个数组:

const data = { "a/a/something": "something/ehere", "a/b/somethingelse": "something/else/here", "a/b/somethingdifferent": "something/else/different", "a/c/somethingess": "something/else/somethingess", "b/a/somethingess": "something/else/somethingess", "b/a/somethingdifferent": "something/else/somethingess", "b/b/somethingdifferentasdasd": "something/else/somethingdifferent", };
const sort = { "a": ["something", "somethingdifferent", "somethingelse"], "b": ["somethingess", "somethingdifferentasdasd"] }

const splitter = (s) => {
  let arr = s.split('/'), index = sort[arr[0]].indexOf(arr[2])
  return ({ k: arr[0], v: index < 0 ? Number.MAX_SAFE_INTEGER : index})
}
const sorter = (a, b) => splitter(a).v - splitter(b).v
const result = Object.entries(
    Object.keys(data)
    .reduce((r, c) => (r[splitter(c).k] = [...r[splitter(c).k] || [], c], r), {})
  )
  .map(([k, v]) => v.sort(sorter))
  .reduce((r, c) => r.concat(c))
  .map(x => ({[x] : data[x]}))

console.log(result)

您将获得有保证的索引顺序和正确/推荐输出。您不能依赖对象道具顺序。

答案 1 :(得分:1)

您可以尝试以下方法处理您的情况

var data = {
    "a/a/something": "something/ehere",
    "a/b/somethingelse": "something/else/here",
    "a/b/somethingdifferent": "something/else/different",
    "a/c/somethingess": "something/else/somethingess",
    "b/a/somethingess": "something/else/somethingess",
    "b/a/somethingdifferent": "something/else/somethingess",
    "b/b/somethingdifferentasdasd": "something/else/somethingdifferent",
};

var sort = {
    "a": ["something", "somethingdifferent", "somethingelse"],
    "b": ["somethingess", "somethingdifferentasdasd"]
}

let tmpData = {}
for(let [key, value] of Object.entries(data)) {
  tmpData[key.split('/')[0]] = tmpData[key.split('/')[0]] || {}
  tmpData[key.split('/')[0]][key.split('/')[2]] = { [key]: value, value: 999 }
}

let tmpResult = {}
for(let [key, args] of Object.entries(sort)) {
  args.forEach((d,i) => tmpData[key][d]['value'] = i)
  
  Object.assign(tmpResult, ... Object.entries(tmpData[key]).map(([, v]) => v).sort((a, b) => a.value - b.value))
}

let {value, ...result} = tmpResult
console.log(result)

答案 2 :(得分:0)

javascript中的对象未排序,因此无法对键进行排序。但是,假设您想以键的排序数组结束...

const inputData = {
  "a/a/something": "something/ehere",
  "a/b/somethingelse": "something/else/here",
  "a/b/somethingdifferent": "something/else/different",
  "a/c/somethingess": "something/else/somethingess",
  "b/a/somethingess": "something/else/somethingess",
  "b/a/somethingdifferent": "something/else/somethingess",
  "b/b/somethingdifferentasdasd": "something/else/somethingdifferent"
};

const sortingFunction = (x, y) => {
  let [a, b, c] = x.split('/');
  let [A, B, C] = y.split('/');
  if (a < A) {
    return -1;
  } else if (A < a) {
    return 1;
  } else {
    if (c < C) {
      return -1;
    } else if (C < c) {
      return 1;
    } else {
      return 0;
    }
  }
};

const sortedKeys = Object.keys(inputData);
sortedKeys.sort(sortingFunction);

console.log(sortedKeys);