0

Following How can I add a key/value pair to a JavaScript object? and Best way to store a key=>value array in JavaScript?, I built my Key/Value map (object).

And I build it like below where MyFunc returns an array:

let MyMap = {}; // object
for(let i = 0; i < MyContainer.length; i++)
{
   // create the key (id of current element) and set its value as array of elements (result from MyFunc)
   await MyFunc(MyContainer[i]).then((response) => MyMap[MyContainer[i].id] = response); 
}

MyMap look like this:

MyMap = 
{
   1: [Object, Object, Object, …] // 13 elements
   2: [Object, Object, Object, …] // 7 elements
   3: [Object, Object, Object, …] // 4 elements
   4: [Object]
   5: [Object]
   6: [Object, Object, Object, …] // 5 elements
   7: [Object, Object, Object, …] // 9 elements
}

I would like to iterate my map (keys) but starting from the key that has the smallest value (The smallest array).

Therefore, I would like to:

  • access MyContainer and pick the element that has id 4, and do stuff (has the smallest array: 1 element)
  • then access MyContainer and pick the element that has id 5, and do stuff
  • then 3
  • then 6
  • .. etc
  • and finally access MyContainer and pick the element that has id 1 and do stuff (has the largest array: 13 elements)

Now since myMap is an object, then I can't sort it.

How can I accomplish this?

Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104

1 Answers1

2

Eventually, you won't be able to use an Object because the order of the keys is not guaranteed.

You can:

  • Use Object.keys(obj) to get the keys of your object as an Array
  • Use those keys to build an Array of objects of your structure, each item in the array being the key/value pair of your original object.
  • Then sort that Arrayof objects based on the length of each item.value within it. The item.value in this case is your original object's values which are Arrays

const obj = {
  "1": [1, 2, 3],
  "2": [1],
  "3": [1, 2],
  "4": [1, 2, 3, 4]
};

// Transform object into a nested array
// Each array item contains the value of a key of your original object,
// which itself is an Array
const arr = Object.keys(obj).reduce((arr, key) => {
 arr.push({ key: key, value: obj[key] });
 
 return arr;
}, [])

// Sort the nested Array based on the length of each item
const sortedArr = arr.sort((a, b) => a.value.length - b.value.length);

console.log(sortedArr);

Same as above but more compact, using chaining

const obj = {
  "1": [1, 2, 3],
  "2": [1],
  "3": [1, 2],
  "4": [1, 2, 3, 4]
};

const sortedArr = Object.keys(obj).reduce((arr, key) => {
  arr.push({ key: key, value: obj[key] });

  return arr;
}, [])
.sort((a, b) => a.value.length - b.value.length)

console.log(sortedArr);
nicholaswmin
  • 21,686
  • 15
  • 91
  • 167
  • I see, but I am still not sure how to implement it. Can you provide a code for my OP? I have properties as IDs, where every ID has an **array of elements** as a value. I want to iterate the properties by the smallest array first (smallest length) – Khalil Khalaf Jun 08 '17 at 21:44
  • 1
    You need to show us an example of the current data structure you have **in code** – nicholaswmin Jun 08 '17 at 21:47
  • Sorry but this is still not clear for me. I edited my OP with my current data structure and the desired process that I would like to have – Khalil Khalaf Jun 08 '17 at 21:59
  • But then how to keep trace of which row to which property (ID)? currently I have `property(can be any integer)` -> `value (array)`, if I convert to a 2d array then I will have `index(starts from 0)` -> `value (row of elements)`. Hence I lose trace of the `any integer` – Khalil Khalaf Jun 08 '17 at 22:01
  • yes but I also want to properties.. I want to start with the smallest array, true, but at the same time I want to know for which ID this array belongs to (In my OP, see where did I get ID from? which turned to be properties, now I want to go to `MyContainer` and pick the element that has the smallest array, then the next, and the next, till I finish it all). – Khalil Khalaf Jun 08 '17 at 22:12
  • Doesn't my last example preserve the properties? – nicholaswmin Jun 08 '17 at 22:15
  • Yes but it did not sort them .. see here: https://s29.postimg.org/ej0m7rbpz/Screen_Shot_2017-06-08_at_6.17.10_PM.png – Khalil Khalaf Jun 08 '17 at 22:17
  • Aye, you're right. That's because Objects do not guarantee the order of the keys. I've just kept it as an `Array` instead with each item in the `Array` keeping the id/key of your original object. Use that for iteration – nicholaswmin Jun 08 '17 at 22:23
  • Let's not fall into x-y problem, maybe I don't need to sort in the first place, see my edited desired behavior? I don't mind populating the data in a different way, as long as after posted loop finishes, I want to access `MyContainer` and pick the element that got smallest result from `Myfunc`, and so on till I iterate them items in `MyContainer` all – Khalil Khalaf Jun 08 '17 at 22:26
  • Open a different question asking just that. FWIW the answer to this question is in my answer. You can't use an Object because the order of the keys is not guaranteed – nicholaswmin Jun 08 '17 at 22:28
  • I just saw your edit, looks like what I am looking for, as long as I have ID and the result attached to it I think I will be fine, thanks – Khalil Khalaf Jun 08 '17 at 22:29