0

I am trying convert a map into a sorted array. There are millions of solutions around, all of which result in one of many many many different errors.

I want to sort this:

public midiCcs: Map<string, ControllerInfo> = new Map<string, ControllerInfo>();

into an array of ControllerInfo ordered by ccMsb:

export class ControllerInfo {
    public name: string = "unassigned";
    public ccMsb: number = 0;
    public ccLsb: number = 0;
    public max: number = 127;
    public min: number = 0;

    constructor(jsonObject: any) {
        this.name = jsonObject.name;
        this.ccMsb = jsonObject.ccMsb;
        this.ccLsb = jsonObject.ccLsb;
        this.max = jsonObject.max;
        this.min = jsonObject.min;
    }

    public toString = () => {
        return `ControllerInfo ${this.name} ${this.min} to ${this.max} ccMsb ${this.ccMsb} ccLsb ${this.ccLsb}`
    }
}

Would greatly appreciated a way out of this minefield.

1
  • [ ...midiCcs.values() ].sort((a, b) => a.ccMsb - b.ccMsb) -- looks good? Commented Sep 14, 2022 at 8:20

2 Answers 2

1

I'm assuming you want to keep the string label. It could be something like this:

Array.from(midiCcs)
    .sort(([label1, item1], [label2, item2]) => item1.ccMsb - item2.ccMsb);
Sign up to request clarification or add additional context in comments.

Comments

0

You can try this approach with sort() (to sort Map by keys) and values() (to get values from Map).

class ControllerInfo {
    public name: string = "unassigned";
    public ccMsb: number = 0;
    public ccLsb: number = 0;
    public max: number = 127;
    public min: number = 0;

    constructor(jsonObject: any) {
        this.name = jsonObject.name;
        this.ccMsb = jsonObject.ccMsb;
        this.ccLsb = jsonObject.ccLsb;
        this.max = jsonObject.max;
        this.min = jsonObject.min;
    }

    public toString = () => {
        return `ControllerInfo ${this.name} ${this.min} to ${this.max} ccMsb ${this.ccMsb} ccLsb ${this.ccLsb}`
    }
}

const midiCcs: Map<string, ControllerInfo> = new Map<string, ControllerInfo>([
    ["C", new ControllerInfo({ name: "C" })],
    ["A", new ControllerInfo({ name: "A" })],
    ["B", new ControllerInfo({ name: "B" })]
]);

const notSortedArray: ControllerInfo[] = Array.from(midiCcs.values());

console.log(notSortedArray)

//shorter version in short()
//const sortedArray: ControllerInfo[] = Array.from(new Map(Array.from(midiCcs).sort()).values());

const sortedArray: ControllerInfo[] = Array.from(new Map(Array.from(midiCcs).sort(([key1], [key2]) => key1.localeCompare(key2))).values());

console.log(sortedArray)

Playground

9 Comments

[...midiCcs].sort()] makes no sense. It's a very roundabout way of sorting by key but also very error-prone way to do that. And most definitely doesn't sort anything (either values or entries) by ccMsb. Moreover, new Map([...midiCcs].sort()).values() is also a roundabout way of getting the values sorted by their key. If that's the intention then Array.from(map).sort((key1], [key2]) => key1.localeCompare(key2)).map(([, value]) => value) is 1. more correct 2. more direct.
Hmm I think it's no harm to use shortcut, but for maintenance, it's important for making the code readable, agreed with you on this.
Why sort the array of entries, then create a map, and then also extract the values from the map to turn them back into an array? What is the purpose of jumping through so many hoops?
Also, this is still only sorting by keys. Not, as the question has asked from the very beginning, property of the value.
I think I am creating my map incorrectly from the server response. midiChart.midiCcs.values() gives me an error "TypeError: midiChart.midiCcs.values is not a function" even though JSON.stringify(midiChart.midiCcs) looks correct.
|

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.