按键对字典排序-Ramda

时间:2019-06-24 07:55:01

标签: javascript typescript ramda.js

在我的程序中,我尝试获取一组项目(在这种情况下为房间),通过某些属性(在其中拥有10个以上座位的房间)对其进行过滤,将它们分组以存储在字典中(按房间所在的区域分组),然后按字典的键排序。

enter image description here

为此,我正在使用以下代码

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项目中看到并运行它。

但是,我遇到以下错误。

  

类型“ Room []”上不存在属性“索引”。ts(2339)

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

有关
  

不能将类型“ NamedRoomDictionary”的参数分配给“只读Room [] []”类型的参数。     类型“ NamedRoomDictionary”缺少类型“只读Room [] []”的以下属性:长度,连接,连接,切片和18个以上。ts(2345)

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

在这里可以看到有效的Repl.it。这不会对组进行排序。它只会将事物分组,然后显示它们。

对于整个打字稿语法/ 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 } ] }

2 个答案:

答案 0 :(得分:3)

给出此列表:

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

要按areaseats >= 10的位置排序房间列表,您可以:

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

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. 然后将结果列表分组到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的使用取决于使用情况。

答案 1 :(得分:2)

您所要求的输出结构不是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>