Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript:从对象id到该对象的反向映射_Javascript_Oop - Fatal编程技术网

JavaScript:从对象id到该对象的反向映射

JavaScript:从对象id到该对象的反向映射,javascript,oop,Javascript,Oop,我有一个类Rectangle,它有一个名为id的属性,指示Rectangle 类矩形{ 建造师(描述){ this.desc=desc this.id=Symbol() } } 稍后,我需要将id放到其他一些数据结构中,我需要一种使用id 要实现这一点,我需要手动创建地图,例如 const r1=新矩形(“第一个”) 常数r2=新矩形('秒') 常数r3=新矩形('第三个') 常数映射={ [r1.id]:r1, [r2.id]:r2, [r3.id]:r3, } 因此,如果需要,我可以获取

我有一个类
Rectangle
,它有一个名为
id
的属性,指示
Rectangle

类矩形{
建造师(描述){
this.desc=desc
this.id=Symbol()
}
}
稍后,我需要将
id
放到其他一些数据结构中,我需要一种使用
id

要实现这一点,我需要手动创建地图,例如

const r1=新矩形(“第一个”)
常数r2=新矩形('秒')
常数r3=新矩形('第三个')
常数映射={
[r1.id]:r1,
[r2.id]:r2,
[r3.id]:r3,
}
因此,如果需要,我可以获取
r1
的引用

map[r1.id]
我想知道是否有一种编程方法可以实现这种反向映射,其中
id
是键,
Rectangle
实例是值

此外,如果有人能为地图提供更好的名称,我将不胜感激。目前,地图的名称
map
并不具有真正的描述性


最后,我想知道我们是否可以去掉
id
,只使用
矩形
实例的引用?我知道答案可能是“视情况而定”,但我认为大多数情况下,对于实例或对象,我们需要一个
id
。我想知道在什么情况下仅使用引用是否不会减少它?

如果您愿意将外部库集成到项目中,一种可能性是使用Lodash的
keyBy
方法。它将一个对象数组作为第一个输入,并使用一个函数来计算结果对象的关键点

如果我以您为例,这将是生成的代码:

import { keyBy } from 'lodash';

const r1 = new Rectangle('first');
const r2 = new Rectangle('second');
const r3 = new Rectangle('third');

const map = keyBy([r1, r2, r3], (rectangle) => rectangle.id);

您仍然需要构建阵列本身,但无论如何都必须这样做。如果您想要一个更复杂的数据结构,您可以创建一个具有数据的内部数组表示形式的类,以及一些访问它的方法。类似这样的东西(我使用的是typescript,javascript与之类似,但没有键入,而且我没有测试这是否仅适用于复制和粘贴,可能需要一些小的调整):

从'lodash'导入{keyBy,filter};
类矩形映射{
私有重新排列:矩形[];
构造函数(){
this.recArray=[];
}
addRectangle(r:矩形):无效{
这个。重新排列。推(r);
}
角度(r:矩形):无效{
this.recArray=过滤器(this.recArray,(rec)=>rec.id!==r.id);
}
getMap(key:string='id'):记录{
返回keyBy(this.recArray,rec=>rec[key]);
}
}
const myRecMap=new RectangleMap();
addRectangle(新矩形('first'));
addRectangle(新矩形('second'));
addRectangle(新矩形('third'));
log(myRecMap.getMap());
一般来说,我总是建议将Lodash用于此类数组/对象操作。它们具有很好的实用功能

我想知道是否有一个程序化的方法来实现这一逆转 映射,其中id是键,矩形实例是值

如果您需要的数据结构是一个以
id
为键的映射,那么如果没有显式的键值插入,就没有现成的方法来实现这一点。您可能有两种选择:

  • 对创建地图的方式有一点改进:

    class Rectangle {
      constructor(desc) {...}
    
      getAsMapEntry() {
        return [this.id, this]
      }
    }
    
    const map = new Map([
      r1.getAsMapEntry(),
      r2.getAsMapEntry(),
      r3.getAsMapEntry()
    ]);
    
    根据您的情况,您应该决定是将
    getAsMapEntry
    方法保留在类
    Rectangle
    中,还是作为实用方法。为了简单起见,我展示了第一种方法,但我可能会选择第二种。此外,我强烈建议您在这里使用
    Map
    class,这对很多人来说都是非常有用的

  • 您可以创建一个新的数据结构,该结构接受
    Rectangle
    s(或者更好地说,接受具有
    id
    属性的所有类型的对象),并且内部有一个映射。这个新类就像一个适配器,使您需要的操作至少更具可读性。不要扩展
    Map
    类,因为此继承将破坏该类,因为您必须彻底更改
    set
    方法的先决条件。更简单的方法是通过组合进行:

    class EntityContainer {
        // accept an array of Rectangle (or objects having the id property)
        constructor(entities) {
            this._internalMap = new Map(entities.map(e => [e.id, e]));
        }
    
        _assertIsEntity(entity) {
            if (!entity.id)
                throw "not an entity"
        }
    
        insertOrUpdate(entity) {
            this._assertIsEntity(entity);
            this._internalMap.set(entity.id, entity);
        }
    
        deleteByEntity(entity) {
            this._assertIsEntity(entity);
            this.deleteById(entity.id);
        }
    
        deleteById(id) {
            this._internalMap.delete(id)
        }
    
        getById(id) {
            this._internalMap.get(id);
        }
    }
    
这种方法的好处是,您可以将基于
id
的逻辑隐藏在
EntityContainer
类中,这意味着您可以插入实体,而不是id实体对。当然,如果您需要,也可以使用
deleteByEntity
进行删除。您也可以验证实体,并且通常可以对所做的操作进行更多的控制,但需要维护一个新类。当您编写的方法只是投影
\u internalMap
方法时,缺点就出现了,请参见
getById
。这不是很漂亮,但在我看来可以接受,如果你必须这样做,只有几个方法

另外,如果有人能给我的名字起个更好的名字,我将不胜感激 地图-现在名称地图不是真正的描述性

当然,这是你必须决定的事情,取决于它的目的

最后,我想知道我们是否可以去掉id,只使用 矩形实例?我知道答案可能是“视情况而定”,但是 我认为大多数情况下,我们需要一个实例或应用程序的id 物体。我想知道在什么情况下只使用引用是否是正确的 你不打算剪掉它吗


同样,您没有向我们提供足够的信息,就是否更适合使用引用或
id
属性向您提供建议(只是为了说明,没有规则,一如既往)。根据您的评论“它是一个更大系统的一部分,
id
可能是一个很好的折衷方案,因为它更容易在多个组件之间创建关系,尤其是当涉及到外部数据存储时。

我认为最好在Rec中创建两个静态属性
class EntityContainer {
    // accept an array of Rectangle (or objects having the id property)
    constructor(entities) {
        this._internalMap = new Map(entities.map(e => [e.id, e]));
    }

    _assertIsEntity(entity) {
        if (!entity.id)
            throw "not an entity"
    }

    insertOrUpdate(entity) {
        this._assertIsEntity(entity);
        this._internalMap.set(entity.id, entity);
    }

    deleteByEntity(entity) {
        this._assertIsEntity(entity);
        this.deleteById(entity.id);
    }

    deleteById(id) {
        this._internalMap.delete(id)
    }

    getById(id) {
        this._internalMap.get(id);
    }
}
const r1 = new Rectangle('first')
const r2 = new Rectangle('second')
const r3 = new Rectangle('third')

const input = [r1, r2, r3];
const map = input.reduce((output, rect) => ({...output, [rect.id]: rect}), {})
console.log(map)
const r1 = new Rectangle('first')
const r2 = new Rectangle('second')
const r3 = new Rectangle('third')

const rectangles = [r1, r2, r3];
const map = rectangles.reduce((output, rectangle) => ({...output, [rectangle.id]: rectangle}), {})
console.log(map)