C# 如何根据依赖项在数组中重新排列项?并检测任何循环依赖关系

C# 如何根据依赖项在数组中重新排列项?并检测任何循环依赖关系,c#,arrays,sorting,dependencies,cyclic,C#,Arrays,Sorting,Dependencies,Cyclic,给定类型: class Field{ public string Name{get;set;} public string[] DependsOn{get;set;} } 假设我有一个字段项的数组: List<Field> fields = new List<Field>(); fields.Add(new Field() { Name = "FirstName" }); fields.Add(new Field() { Name = "FullName

给定类型:

class Field{
    public string Name{get;set;}
    public string[] DependsOn{get;set;}
}
假设我有一个
字段
项的数组:

List<Field> fields = new List<Field>();
fields.Add(new Field() { Name = "FirstName" });
fields.Add(new Field() { Name = "FullName", 
                         DependsOn = new[] {"FirstName","LastName"}});
fields.Add(new Field() { Name = "Age", 
                         DependsOn = new[] { "DateOfBirth" } });
fields.Add(new Field() { Name = "LastName" });
fields.Add(new Field() { Name = "DateOfBirth" });
列表字段=新列表();
添加(新字段(){Name=“FirstName”});
添加(新字段(){Name=“FullName”,
DependsOn=new[]{“FirstName”,“LastName”});
添加(新字段(){Name=“Age”,
DependsOn=new[]{“出生日期”});
添加(新字段(){Name=“LastName”});
添加(新字段(){Name=“DateOfBirth”});
因此,很明显,我们按照以下顺序购买产品:

  • 名字
  • 全名
  • 年龄
  • 姓氏
  • 出生日期
  • 我的第一个问题: 重新排列列表/数组中的项目的最佳方式是什么,以便将相关列(全名和年龄)放在它们所依赖的列之后,例如:

  • 名字
  • 姓氏
  • 全名
  • 出生日期
  • 年龄
  • 所以像Age这样的字段总是在它所依赖的出生日期之后

    我的第二个问题: 是否有方法检测循环依赖关系?i、 e.何时
    Field1
    取决于
    Field2

    Field2
    取决于
    Field3

    Field3
    取决于
    Field1


    这样我们就不会陷入圈套。e、 大学毕业后,你需要2年的工作经验才能找到工作。但是要获得工作经验,你首先需要得到这份工作。

    听起来你需要按拓扑顺序对这些项目进行排序。网络上有很多页面,也许维基百科是一个很好的起点:
    听起来您需要按拓扑顺序对这些项目进行排序。网络上有很多页面,也许维基百科是一个很好的起点: 谢谢你的提示 实际上,我在java中发现了类似的东西

    以下是C#改编:

    class Class1
    {
        public static void Run()
        {
            doTopologicalTest();
        }
    
        private static void doTopologicalTest()
        {
            List<Field> fields = new List<Field>();
            fields.Add(new Field() { Name = "FirstName" });
            fields.Add(new Field()
            {
                Name = "FullName",
                DependsOn = new[] { "FirstName", "LastName" }
            });
            fields.Add(new Field()
            {
                Name = "Age",
                DependsOn = new[] { "DateOfBirth" }
            });
            fields.Add(new Field() { Name = "LastName" });
            fields.Add(new Field() { Name = "DateOfBirth" });
    
            foreach (var field in fields)
            {
                Console.WriteLine(field.Name);
                if(field.DependsOn != null)
                    foreach (var item in field.DependsOn)
                    {
                        Console.WriteLine(" -{0}",item);
                    }
            }
    
            Console.WriteLine("\n...Sorting...\n");
    
            int[] sortOrder = getTopologicalSortOrder(fields);
    
            for (int i = 0; i < sortOrder.Length; i++)
            {
                var field = fields[sortOrder[i]];
                Console.WriteLine(field.Name);
                if (field.DependsOn != null)
                    foreach (var item in field.DependsOn)
                    {
                        Console.WriteLine(" -{0}", item);
                    }
            }
    
        }
    
        private static int[] getTopologicalSortOrder(List<Field> fields)
        {
            TopologicalSorter g = new TopologicalSorter(fields.Count);
            Dictionary<string, int> _indexes = new Dictionary<string, int>();
    
            //add vertices
            for (int i = 0; i < fields.Count; i++)
            {
                _indexes[fields[i].Name.ToLower()] = g.AddVertex(i);
            }
    
            //add edges
            for (int i = 0; i < fields.Count; i++)
            {
                if (fields[i].DependsOn != null)
                {
                    for (int j = 0; j < fields[i].DependsOn.Length; j++)
                    {
                        g.AddEdge(i,
                            _indexes[fields[i].DependsOn[j].ToLower()]);
                    }
                }
            }
    
            int[] result = g.Sort();
            return result;
    
        }
    
    
        class Field
        {
            public string Name { get; set; }
            public string[] DependsOn { get; set; }
        }
    }
    
    Class1类
    {
    公共静态无效运行()
    {
    点拓扑测试();
    }
    私有静态void点拓扑测试()
    {
    列表字段=新列表();
    添加(新字段(){Name=“FirstName”});
    fields.Add(新字段()
    {
    Name=“FullName”,
    DependsOn=new[]{“FirstName”,“LastName”}
    });
    fields.Add(新字段()
    {
    Name=“Age”,
    DependsOn=new[]{“出生日期”}
    });
    添加(新字段(){Name=“LastName”});
    添加(新字段(){Name=“DateOfBirth”});
    foreach(字段中的变量字段)
    {
    Console.WriteLine(字段名称);
    如果(field.DependsOn!=null)
    foreach(字段DependsOn中的变量项)
    {
    Console.WriteLine(“-{0}”,项);
    }
    }
    Console.WriteLine(“\n…排序…\n”);
    int[]sortOrder=getTopologicalSortOrder(字段);
    for(int i=0;i
    以及TopologicalSort.cs的代码

    class TopologicalSorter
    {
        #region - Private Members -
    
        private readonly int[] _vertices; // list of vertices
        private readonly int[,] _matrix; // adjacency matrix
        private int _numVerts; // current number of vertices
        private readonly int[] _sortedArray;
    
        #endregion
    
        #region - CTors -
    
        public TopologicalSorter(int size)
        {
            _vertices = new int[size];
            _matrix = new int[size, size];
            _numVerts = 0;
            for (int i = 0; i < size; i++)
                for (int j = 0; j < size; j++)
                    _matrix[i, j] = 0;
            _sortedArray = new int[size]; // sorted vert labels
        }
    
        #endregion
    
        #region - Public Methods -
    
        public int AddVertex(int vertex)
        {
            _vertices[_numVerts++] = vertex;
            return _numVerts - 1;
        }
    
        public void AddEdge(int start, int end)
        {
            _matrix[start, end] = 1;
        }
    
        public int[] Sort() // toplogical sort
        {
            while (_numVerts > 0) // while vertices remain,
            {
                // get a vertex with no successors, or -1
                int currentVertex = noSuccessors();
                if (currentVertex == -1) // must be a cycle                
                    throw new Exception("ERROR: Graph has cycles");
    
                // insert vertex label in sorted array (start at end)
                _sortedArray[_numVerts - 1] = _vertices[currentVertex];
    
                deleteVertex(currentVertex); // delete vertex
            }
    
            // vertices all gone; return sortedArray
            return _sortedArray;
        }
    
        #endregion
    
        #region - Private Helper Methods -
    
        // returns vert with no successors (or -1 if no such verts)
        private int noSuccessors()
        {
            for (int row = 0; row < _numVerts; row++)
            {
                bool isEdge = false; // edge from row to column in adjMat
                for (int col = 0; col < _numVerts; col++)
                {
                    if (_matrix[row, col] > 0) // if edge to another,
                    {
                        isEdge = true;
                        break; // this vertex has a successor try another
                    }
                }
                if (!isEdge) // if no edges, has no successors
                    return row;
            }
            return -1; // no
        }
    
        private void deleteVertex(int delVert)
        {
            // if not last vertex, delete from vertexList
            if (delVert != _numVerts - 1)
            {
                for (int j = delVert; j < _numVerts - 1; j++)
                    _vertices[j] = _vertices[j + 1];
    
                for (int row = delVert; row < _numVerts - 1; row++)
                    moveRowUp(row, _numVerts);
    
                for (int col = delVert; col < _numVerts - 1; col++)
                    moveColLeft(col, _numVerts - 1);
            }
            _numVerts--; // one less vertex
        }
    
        private void moveRowUp(int row, int length)
        {
            for (int col = 0; col < length; col++)
                _matrix[row, col] = _matrix[row + 1, col];
        }
    
        private void moveColLeft(int col, int length)
        {
            for (int row = 0; row < length; row++)
                _matrix[row, col] = _matrix[row, col + 1];
        }
    
        #endregion
    }
    
    类拓扑排序器
    {
    #地区-私人会员-
    私有只读int[]\u顶点;//顶点列表
    私有只读int[,]_矩阵;//邻接矩阵
    private int _numVerts;//当前顶点数
    私有只读int[]\u-sortedArray;
    #端区
    #区域因素-
    公共拓扑排序器(整数大小)
    {
    _顶点=新整数[大小];
    _矩阵=新整数[大小,大小];
    _numVerts=0;
    对于(int i=0;i0)//保留顶点时,
    {
    //获取没有后继对象的顶点,或-1
    int currentVertex=noSuccessors();
    if(currentVertex==-1)//必须是一个循环
    抛出新异常(“错误:图形有循环”);
    //在排序数组中插入顶点标签(从末尾开始)
    _sortedArray[\u numVerts-1]=\u顶点[currentVertex];
    deleteVertex(currentVertex);//删除顶点
    }
    //顶点都消失了;回到Darray
    返回(darray);;
    }
    #端区
    #区域-私有助手方法-
    //返回没有后继项的vert(如果没有后继项,则返回-1)