当前位置: 首页 > 知识库问答 >
问题:

javascript - 从扁平的数据结构数组,转换为嵌套式的数据结构,请问需要什么算法才能实现呢?

井唯
2024-08-19

请问下,这种算法叫什么呢,如何才能进行实现:

定义的interface如下:

type PropertyDataType = {
  name: string,
  isFrom: ItemDataType,  // 从哪个类/抽象类/接口来的
  value: string | number |  undefined,  // 接口无实现 = undefined
}

type MethodDataType = {
  name: string, 
  isFrom: ItemDataType,
  value: string | undefined  // 接口无实现 = undefined
  isAbstract: boolean  // 是否是抽象方法
}

//#region 类接口之间的关系
type InheritanceRelationType = {
  name: 'inheritance',
  relationToId: ItemDataTypeId
}

type ImplementationRelationType = {
  name: 'implementation',
  relationToId: ItemDataTypeId
}

type AggregationRelationType = {
  name: 'aggregation',
  relationToId: ItemDataTypeId
}

type CompositionRelationType = {
  name: 'composition',
  relationToId: ItemDataTypeId
} 

type RelationType = InheritanceRelationType | ImplementationRelationType | AggregationRelationType | CompositionRelationType
//#endregion

type ItemDataTypeId = string | number

// 类数据类型: 类/抽象类/接口
export type ItemDataType = {
  id: ItemDataTypeId,
  type: 'Class' | 'AbstractClass' | 'Interface', 
  name: string, // 类名称
  properties: PropertyDataType[],  // 属性
  methods: MethodDataType[],
  relations: RelationType[]  // 与其他ItemDataType的关系
}

现在有数据(很多的ItemDataType类型数据组成的数组):

const dataList = <ItemDataType[]>[
  {
    id: 1,
    type: 'Class',
    name: 'AnimalBase',
    properties: [],
    methods: [],
    relations: []
  },
  {
    id: 2,
    type: 'Class',
    name: 'Animal',
    properties: [],
    methods: [],
    relations: [{name: 'inheritance', relationToId: 1}]
  },
  {
    id: 3,
    type: 'Class',
    name: 'Cat',
    properties: [],
    methods: [],
    relations: [{name: 'inheritance', relationToId: 2}]
  }
]

想要
设定一个方法:
getInheritanceChain(id:number): ReturnType
返回ReturnType数据内容为嵌入式数据,举例:

{
  name: 'Cat',
  comesFrom: [
    {
      relationName: 'inheritance',
      name: 'Animal',
      type: 'Class',
      comesFrom: [
        {
          relationName: 'inheritance',
          name: 'AnimalBase',
          type: 'Class',
          comesFrom: []
        }
      ]
    }
  ]
}

请问这个需要如何进行处理呢?是否有现有的库进行直接处理呢?

共有2个答案

丁立果
2024-08-19
const map = new Map(dataList.map(item => [item.id, item]))

interface ComesFrom {
    relationName: string
    name: string
    type: string
    comesFrom?: ComesFrom[]
}
function getRelations(item: ItemDataType): ComesFrom[] {
    return item.relations.map(r => {
        const item = map.get(r.relationToId)
        if (item === undefined) throw new Error('relationToId is invalid')
        return {
            relationName: r.name,
            name: item.name,
            type: item.type,
            comesFrom: getRelations(item)
        }
    })
}

function getInheritanceChain(id: ItemDataTypeId) {
    const item = map.get(id)

    return item
        ? {
                name: item.name,
                comesFrom: getRelations(item)
          }
        : undefined
}

console.log(getInheritanceChain(3))
{
  name: "Cat",
  comesFrom: [
    {
      relationName: "inheritance",
      name: "Animal",
      type: "Class",
      comesFrom: [
        {
          relationName: "inheritance",
          name: "AnimalBase",
          type: "Class",
          comesFrom: []
        }
      ]
    }
  ]
}
邢硕
2024-08-19

要实现从扁平的 ItemDataType 数组到嵌套式数据结构的转换,你可以使用递归算法来遍历和处理这些关系。在这个例子中,主要的关系是继承(inheritance),但你可以根据需要扩展到其他关系类型。

下面是一个基本的实现方法,不依赖于现有的库,而是手动编写递归函数来处理继承链:

function getInheritanceChain(dataList: ItemDataType[], id: ItemDataTypeId): ReturnType | null {
  // 查找当前ID的项
  const currentItem = dataList.find(item => item.id === id);
  if (!currentItem) return null;

  // 递归构建继承链
  function buildChain(item: ItemDataType): ReturnType {
    const chainItem: ReturnType = {
      name: item.name,
      type: item.type,
      comesFrom: []
    };

    // 处理继承关系
    item.relations.forEach(relation => {
      if (relation.name === 'inheritance') {
        const parentItem = dataList.find(parent => parent.id === relation.relationToId);
        if (parentItem) {
          chainItem.comesFrom.push(buildChain(parentItem));
        }
      }
    });

    return chainItem;
  }

  return buildChain(currentItem);
}

// 返回值类型定义
interface ReturnType {
  name: string;
  type: 'Class' | 'AbstractClass' | 'Interface';
  comesFrom: ReturnType[];
}

// 示例数据
const dataList = [
  // ...(如你所示的数据)
];

// 使用示例
console.log(getInheritanceChain(dataList, 3));

在这个实现中,getInheritanceChain 函数首先查找具有给定ID的项。然后,它调用 buildChain 函数来递归地构建继承链。buildChain 函数会检查当前项的继承关系,并对每个继承关系递归调用自身以构建嵌套的 comesFrom 数组。

这种方法不需要额外的库,并且可以根据需要轻松地扩展到处理其他类型的关系。此外,通过递归方式,你可以灵活地处理任何深度的继承链。

 类似资料:
  • 数组是一种线性表数据结构,它用一组连续的内存空间,来存储一组具有相同类型的数据(JS里可以是任意类型)。 关键点:连续的存储空间(数组可以进行随机访问) // js let data = [] // c int data[200] = { 0 }; // 编译时 就已经确定所有的值为零 // java int data[] = new int[3]; // 开辟了一个长度为3的数组 在Ch

  • 几天来,我一直在考虑这个“简单”的练习,结果被困住了。我都快疯了。我需要将嵌套数组转换为HTML。下面是数组的示例: 而预期的结果应该是这样的: 我已经从一个helper函数开始(从数组创建每个标记),下面是它现在的样子: 到目前为止还不错。当我试图创建实际的HTML构建器函数时,这个棘手的部分就开始了。我想迭代数组的每个元素,检查它是否有一个嵌套的元素(子),保存指定的标记,再深入一些。 到目前

  • 突然很好奇,在前端日常开发中,需要经常和 dom 打交道,所以经常要用到 querySelectorAll 和 document.body.getChildren 等方法,但是它们的返回值都是一个类数组类型,我们就需要用一些方法,比如拓展运算符、Array.from 等将它们转换为真数组 来进行操作。 问题: 类数组的意义在哪里?dom 的哪些方法为什么不直接返回一个真数组呢?

  • 包含了多种基于 JavaScript 的算法与数据结构。每种算法和数据结构都有自己的 README,包含相关说明和链接,以便进一步阅读 (还有 YouTube 视频) 。

  • 我想将此Firebase实时数据库结构转换为fiRecovery数据结构,请提供一些帮助。 我想要那种结构,比如Posts(集合)/pin(集合)/pid(文档)/然后是post描述,但是我知道一个集合不能包含另一个集合,所以我应该怎么做? “所有_帖子”节点包含pid和pin,仅用于共享该帖子,然后使用pin和pid获取帖子详细信息。 在我的结构中还有一件事发布-

  • 我需要展平一个数据帧,以便将其与Spark(Scala)中的另一个数据帧连接起来。 基本上,我的2个数据帧有以下模式: 数据流1 DF2 老实说,我不知道如何使DF2变平。最后,我需要连接DF.field4 = DF2.field9上的2个数据帧 我用的是2.1.0 我的第一个想法是使用爆炸,但在Spark 2.1.0中已经被否决了,有人能给我一点提示吗?