按键排序字典 - Ramda

Sort dictionary by key - Ramda

在我的程序中,我试图获取一组项目(在本例中为房间),通过一些 属性(超过 10 个座位的房间)对其进行过滤,将它们分组存储在字典中(按房间所在区域分组),然后按字典键排序。

为此,我使用以下代码

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)

这可以在这个 Repl.it 项目中看到并 运行。

但是,我收到以下错误。

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

以上错误与room.indexsort(ascend(room => room.index), rooms)

有关

Argument of type 'NamedRoomDictionary' is not assignable to parameter of type 'readonly Room[][]'. Type 'NamedRoomDictionary' is missing the following properties from type 'readonly Room[][]': length, concat, join, slice, and 18 more.ts(2345)

上述错误与行 sort(ascend(room => room.index), rooms) 上的 rooms 有关。

可以在此处看到有效的 Repl.it。这不会对组进行排序。它只是把东西分组然后显示出来。

我对整个 typescript 语法/Ramda 库还很陌生,所以任何解决这个问题的建议都将不胜感激。


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 } ] }

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 } ] }

鉴于此列表:

[
  {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} ];

为了获得按 area 排序的房间列表,其中 seats >= 10,您可以:

  1. 只保留 seats >= 10
  2. 的房间
  3. 然后在 area
  4. 上对结果列表进行排序

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>

要按 area(其中 seats >= 10)对房间进行分组,您可以

  1. 只保留 seats >= 10
  2. 的房间
  3. 然后将结果列表分组到 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>

这两个片段之间的区别在于 sortBygroupBy 的使用取决于用例。

您请求的输出结构不是 Ramda 专门设计来支持的。对象在 JS 中扮演着双重角色,作为字典和记录。但是这两种类型都没有内在的顺序。 Ramda 希望将具有相同键的相同值的对象视为本质上相等。因此 R.equals({a: 1, b: 2}, {b: 2, a: 1} 产生 true。因此,虽然您可以按 area 属性 分组,并且您可以选择对结果的(数组)键进行排序,但 Ramda 不会本质上为您排序结果对象。如果您自己订购,有一天 Ramda 函数可能会为您重新订购。 (Ramda 有时会考虑按字母顺序对对象键进行排序以处理其中的一些问题。)

但是更简单的输出结构很容易实现,其中项目被过滤然后根据它们的组排序,但仍然保存在平面数组中:

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

这与 customcommander 给出的答案基本相同。

如果您想对结果进行进一步排序,比如按座位数降序排列,那么切换到 sortWith:

是有意义的

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>