0

I currently have one object which looks like this:

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

This Object.keys currently is segmented with 3 elements, and all i care about is the first and third [1]/[2]/[3].

I am currently running a foreach that loops through all the object keys but i want to sort it by the criteria 1 and criteria 3.

My Loop:

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

My sort:

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

The objective is so it would check whether key a/a/something and when it reaches the loop, it should check the sort object before it hits the foreach.

Expected result prior to 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
  • 2
    What exactly is the expected output? Commented Nov 12, 2018 at 19:31
  • 1
    @Akrion, just added in the expected result prior to foreach Commented Nov 12, 2018 at 19:38
  • Its not clear what you want but you should probably .split("/") somewhere Commented Nov 12, 2018 at 19:59

3 Answers 3

1

You can try below approach to handle your scenario

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)

Sign up to request clarification or add additional context in comments.

Comments

1

You could do something like this:

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)

The idea is to get the keys via Object.keys then group them by index [0], sort them and then compose the final object.

Note: Object props order is not guaranteed:

An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.

Although the SO console would show the desired order in Chrome console you would not get the same output. Just FYI.

So with that in mind if you replace the last line and instead of reduce you do map so the end result is an array:

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)

You would get a guaranteed index order and the correct / recommended output. You can not rely on object prop order.

4 Comments

Thank you, question, where in this are you referencing the sort object? how does it know how to sort
Sorry from your question the impression is that you would take the first data and sort it using the [0]/[1]/[2] indexes. So this takes the input from data and taking the keys sorts them by only coparing [0]/[2] indexes. If this is not correct let me know.
Sorry Akrion, i think i may have confused everyone. var sort should be what my sorting should be based on, the idea behind is that i currently have "a" object which has an array of how it should sort,. However, to split it up, you need [0] and [2]
Updated the answer
0

Objects in javascript are not sorted, so you cannot sort keys. However, let's say you wanted to end up with a sorted array of the keys...

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.