Arranging a dictionary by its keys using Ramda

My task involves manipulating an array of items (specifically, rooms) in a program. I need to filter the array based on a certain property (rooms with more than 10 seats), group them by another property (the area the room is in), store them in a dictionary, and finally sort them by the dictionary's key.

https://i.sstatic.net/KSsoBm.png

To achieve this, I have implemented the following code:

import { ascend, filter, groupBy, pipe, sort } from "ramda";

class Room {
    // Number of seats in the room
    public seats!: number;

    // Area on site, an area can have many rooms
    public area!: string;

    // Name of the room
    public room!: number;
}

class NamedRoomDictionary {
    [index: string]: Room[];
}

const GetRoomsWithMoreThanTenSeats = (rooms: Room[]): Room[] =>
    filter(room => room.seats > 10, rooms);

const GroupByArea = (rooms: Room[]): NamedRoomDictionary =>
    groupBy(room => room.area, rooms);

const SortByArea = (rooms: NamedRoomDictionary): NamedRoomDictionary =>
    sort(ascend(room => room.index), rooms)

const SortBigRoomsByArea = pipe(
    GetRoomsWithMoreThanTenSeats,
    GroupByArea,
    SortByArea
);

const rooms: Room[] = [
  {room: 1, area: 'A', seats: 15},
  {room: 2, area: 'D', seats: 5},
  {room: 3, area: 'R', seats: 8},
  {room: 4, area: 'E', seats: 14},
  {room: 5, area: 'A', seats: 458},
  {room: 6, area: 'F', seats: 10},
  {room: 7, area: 'A', seats: 4},
  {room: 8, area: 'A', seats: 256},
  {room: 9, area: 'D', seats: 100}
];

const sorted = SortBigRoomsByArea(rooms);

console.log(sorted)

You can view and run this project on Repl.it.

Despite my efforts, I encountered the following errors:

Property 'index' does not exist on type 'Room[]'.ts(2339)

The error above pertains to room.index on the line

sort(ascend(room => room.index), rooms)
.

Argument of type 'NamedRoomDictionary' is not assignable to parameter of type 'readonly Room[][]'. Type 'NamedRoomDictionary' is missing the properties required by 'readonly Room[][]': length, concat, join, slice, and several others.ts(2345)

This second error is related to rooms on the line

sort(ascend(room => room.index), rooms)
.

A functional example can be seen on Repl.it. This version successfully groups the rooms but doesn't implement sorting.

Being relatively new to TypeScript syntax and the Ramda library, I would appreciate any guidance on resolving these issues.


Output of just grouping Repl.it

{ A:
   [ { room: 1, area: 'A', seats: 15 },
     { room: 5, area: 'A', seats: 458 },
     { room: 8, area: 'A', seats: 256 } ],
  E: [ { room: 4, area: 'E', seats: 14 } ],
  D: [ { room: 9, area: 'D', seats: 100 } ] }

Desired output of sorting repl.it

{ A:
   [ { room: 1, area: 'A', seats: 15 },
     { room: 5, area: 'A', seats: 458 },
     { room: 8, area: 'A', seats: 256 } ],
  D: [ { room: 9, area: 'D', seats: 100 } ],
  E: [ { room: 4, area: 'E', seats: 14 } ] }

Answer №1

Consider this scenario:

[
  {room: 1, area: 'A', seats: 15},
  {room: 2, area: 'D', seats: 5},
  {room: 3, area: 'R', seats: 8},
  {room: 4, area: 'E', seats: 14},
  {room: 5, area: 'A', seats: 458},
  {room: 6, area: 'F', seats: 10},
  {room: 7, area: 'A', seats: 4},
  {room: 8, area: 'A', seats: 256},
  {room: 9, area: 'D', seats: 100} ];

To obtain a sorted sequence of rooms according to area where seats >= 10, follow these steps:

  1. Retain only the rooms with seats greater than or equal to 10
  2. Subsequently arrange the filtered list based on the area

const rooms = [
  {room: 1, area: 'A', seats: 15},
  {room: 2, area: 'D', seats: 5},
  {room: 3, area: 'R', seats: 8},
  {room: 4, area: 'E', seats: 14},
  {room: 5, area: 'A', seats: 458},
  {room: 6, area: 'F', seats: 10},
  {room: 7, area: 'A', seats: 4},
  {room: 8, area: 'A', seats: 256},
  {room: 9, area: 'D', seats: 100} ];


const z = compose(sortBy(prop('area')), filter(propSatisfies(lte(10), 'seats')));

console.log(

  z(rooms)

)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {compose, sortBy, prop, filter, propSatisfies, lte} = R;</script>

To categorize rooms by area where seats >= 10, proceed as follows:

  1. Filter out the rooms with seats greater than or equal to 10
  2. Next, group the filtered list based on the area

const rooms = [
  {room: 1, area: 'A', seats: 15},
  {room: 2, area: 'D', seats: 5},
  {room: 3, area: 'R', seats: 8},
  {room: 4, area: 'E', seats: 14},
  {room: 5, area: 'A', seats: 458},
  {room: 6, area: 'F', seats: 10},
  {room: 7, area: 'A', seats: 4},
  {room: 8, area: 'A', seats: 256},
  {room: 9, area: 'D', seats: 100} ];


const z = compose(groupBy(prop('area')), filter(propSatisfies(lte(10), 'seats')));

console.log(

  z(rooms)

)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {compose, groupBy, prop, filter, propSatisfies, lte} = R;</script>

The distinction between the two code snippets lies in the utilization of either sortBy or groupBy, depending on the specific requirement.

Answer №2

Ramda is not specifically designed to support the output structure you are requesting. In JavaScript, objects serve as dictionaries and records, but they do not have an inherent order. Ramda considers objects with the same keys and values to be equal, so sorting them can result in unexpected behavior. While you can group by a property like `area` and manually sort the keys of the result array, Ramda does not intrinsically order objects for you. Additionally, if you manually order it, a Ramda function may reorder it at some point.

However, achieving a simpler output structure where items are filtered and sorted according to their group in a flat array is straightforward:

const sortBigRoomsByArea = pipe (
  filter ( ({seats}) => seats > 10 ),
  sortBy (prop ('area'))
)

This approach is similar to the one provided by customcommander.

If you require further sorting, such as sorting by descending number of seats, using `sortWith` would be appropriate:

const sortBigRoomsByArea = pipe (
  filter ( ({seats}) => seats > 10 ),
  sortWith ([
    ascend ( prop ('area') ),
    descend ( prop ('seats') )
  ])
)

const rooms= [{room: 1, area: 'A', seats: 15}, {room: 2, area: 'D', seats: 5}, {room: 3, area: 'R', seats: 8}, {room: 4, area: 'E', seats: 14}, {room: 5, area: 'A', seats: 458}, {room: 6, area: 'F', seats: 10}, {room: 7, area: 'A', seats: 4}, {room: 8, area: 'A', seats: 256}, {room: 9, area: 'D', seats: 100}]

console.log (
  sortBigRoomsByArea (rooms)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const {ascend, descend, filter, pipe, prop, sortWith} = R   </script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Obtain the text content of a div using JavaScript

Hello, I am new to Javascript! I have a table structure that looks like this: <table id='master_tbl'> <tbody> <tr id="master_hr'> <td class="myclass"> <table> <tbody ...

I am experiencing an issue with the PUT method on my API as it is not correctly setting the req.body data

Below is the code snippet for implementing the PUT method: [/api/[id].ts] case "PUT": try { const user = await UserModel.findOneAndUpdate( { _id: id, }, { $set: req.body, ...

Is there a way to verify the react-query queries prior to running them?

Consider this scenario where I have a query to retrieve a list: const list = useQuery('list', fetcher); However, I require a pre-checking function before react-query triggers the execution. Something like this: const appQueryClient = new QueryCl ...

TypeScript - Minimize redundancy when defining types for a class and its constructor arguments

Here is a class structure I am currently using: class Person { id?: string = uuid(); name: string; constructor(data: Person) { _.merge(this, data); } } The 'uuid' function generates an id and '_' refers to loda ...

Can you explain the rationale behind html and js?

I am experiencing an issue with my code. When I click on the "click" button, the color changes as expected but the console log is showing that the code is not working according to the logic I have implemented. Initially, the color is black which is correc ...

TypeScript PatchBaseline with AWS CDK

I am currently working with the AWS CDK and TypeScript, utilizing the @aws-cdk/aws-ssm library to create a PatchBaseline. While I have successfully created the Patch baseline, I'm encountering difficulties when attempting to define approvalRules. I ca ...

Avoid using references when removing elements from an array in JavaScript

For a straightforward logging system, I've devised a method of storing arrays as log entries within a single array. Here's how the code functions: var myarr = new Array(); var secondarr = new Array(4,5,6); myarr.push(secondarr); secondarr.length ...

Techniques for dynamically counting rows in a table using JavaScript

I'm working on a system to create and delete rows, and I want each row to have a unique row number displayed under "Num." However, I'm having trouble implementing this feature. EDIT I found a jQuery snippet that counts the first row but not t ...

Unexpected Timed Out error from Socket.IO adapter when MongoDB connection is lost

I have been experimenting with capturing the disconnection event in mongodb. Everything is working smoothly with this setup: simple.js 'use strict'; var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:2701 ...

Adjust the background color of the header as you scroll

Seeking assistance in adjusting the background color of my header upon scrolling. This is my current implementation: header.component.ts export class HeaderComponent { ngOnInit(): void { const header = document.querySelector('.header'); ...

Retrieve the initial class of an element using either jQuery or JavaScript

I need help with a jQuery function that is not working properly. I have 3 anchors with corresponding divs, and when I click on one of the anchors, I want to display the contents of the corresponding div. The anchors are as follows: <a class="home share ...

What is the process for converting variadic parameters into a different format for the return value?

I am currently developing a combinations function that generates a cartesian product of input lists. A unique feature I want to include is the ability to support enums as potential lists, with the possibility of expanding to support actual Sets in the futu ...

Instructions on how to include a conditional click attribute to a hyperlink

Is there a way to make an anchor tag trigger a function only if a specific variable is set? In this scenario, the variable name is assigned the value of "Shnick", so when the link is clicked it should activate the func() method. However, clicking the link ...

Combining Several Middleware Functions in NextJs 13 for Authentication and Localization

Important Note If you are interested in exploring my code further, you can find the repository here. To access the specific code for the ott-platform, navigate to apps/ott-platform. Please make sure to create an account on Clerk and input your Clerk key i ...

How can you make sure that a class property in TypeScript always matches the name of the class?

Click here for an example interface ICommandHandler<T> { type: string // how can we ensure that this equals T.name? handle(command: T): void; } interface ICommand {} class CreateTaskCommand implements ICommand{} class CreateTaskCommandHandler ...

Determine if an object is already present in a JSON array by comparing their respective IDs

I have a shopping cart stored in JSON format. [{"tuote":{"id":"2","name":"Rengas 2","count":16,"price":"120.00"}},{"tuote":{"id":"1","name":"Rengas 6","count":"4","price":"25.00"}},{"tuote":{"id":"4","name":"Rengas 4","count":"4","price":"85.00"}}] Form ...

Difference between ng-controller variable and ng-init variable

When working with the code snippet below in angularJS, <script type="text/javascript"> angular.module('app').controller('add', ['$scope',function($scope) { $scope.name = "Bonita Ln"; }]); </script& ...

Using Node.js: Interacting with npm inside a module

Is there a more efficient way to implement self-updating functionality for a globally installed module than using the code snippet below? require("child_process").exec("npm update -g module-name"); I came across some documentation regarding installing np ...

What is the best way to retrieve an object from a loop only once the data is fully prepared?

Hey, I'm just stepping into the world of async functions and I could use some help. My goal is to return an object called name_dates, but unfortunately when I check the console it's empty. Can you take a look at my code? Here's what I have ...

Using AngularJS to filter options in a dropdown list and trigger a function with ng-change

I have a dropdown menu that is being formatted using filters to display the text in a certain way. I need to send the selected item's ID value to the controller instead of just the name: <select ng-model="my_field" ...