0

I am trying to sort a List by other values inside the List.

When I am trying to accomplish: When I add a value to list I will be using a method that contains the value, and a string[] of values that represents it's dependencies.

I want to sort the list, by the values in the string[] inside the ListObject

Here is a programmatic example:

public class ListObject {
    private string name;
    private string[] dependencies;
    private object value;

    public ListObject(string name, string[] dependencies, object value) {
        this.name = name;
        this.dependencies = dependencies;
        this.value = value;
    }
}

public class ExampleClass {
    public static void Main(string[] args) {
        List<ListObject> list = new List<ListObject>();
        list.Add(new ListObject("ran", new string[] { }, "Value"));
        list.Add(new ListObject("far", new string[] {"thest"}, "Value"));
        list.Add(new ListObject("the", new string[] {"ran"}, "Value"));
        list.Add(new ListObject("thest", new string[] {"the", "ran"}, "Value"));
        list.Add(new ListObject("man", new string[] {"ran", "thest"}, "Value"));

        //What I want the order of the list to become
        /* ran
         * the
         * far
         * thest
         * man
         */
    }
}

More info: I am generating classes at runtime, I need to make sure that if a field has a generated class type, then I need to make sure I generate the class the field depends on before I generate the class the field is located in.

Heirteir
  • 21
  • 6
  • 2
    For starters you should use the correct dictionary if the order matters: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.sorteddictionary-2?view=netframework-4.8 the rest is not really clear to me. But if the problem is indeed keys not being sorted, this will solve it. – X39 Oct 17 '19 at 12:16
  • It actually might be better to use a SortedList, and Sort the values using the DictionaryObject. I'll update the question. – Heirteir Oct 17 '19 at 12:21
  • There is nothing in your code sample that is sorting anything, there is even nothing that compares values (which is at the very heart of sorting). Please **[edit]** the question and improve the code sample so we can see what sorting means in the case, and where it is supposed to happen and how. – Peter B Oct 17 '19 at 12:22
  • I updated my question, to hopefully make what I am trying to accomplish more clear. – Heirteir Oct 17 '19 at 12:31
  • Possible duplicate of [How to Sort a List by a property in the object](https://stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object) – Liam Oct 17 '19 at 12:33
  • TBH... i think you approach this from the wrong side of things. Just carry around some HashSet in which you check if a given *thing* already was written out, otherwise call a recursive method to print it out. Only thing you have to take care then is accidential recursion – X39 Oct 17 '19 at 12:37
  • The are never written out beforehand. I need to sort the list first then write out all values in a specific order. – Heirteir Oct 17 '19 at 12:48

2 Answers2

0

I don't fully undestand the rules and you change the test input, but here is the version that produces the sequence you desired, and more generally is a blueprint for all sort (badam tsh!) of sorting strategies.

using System.Linq;

(...)

public class ListObject
    {
        public string name {get;} // Made into properties and public

(...)

       List<ListObject> list = new List<ListObject>();
       list.Add(new ListObject("ran", new string[] { }, "Value"));
       list.Add(new ListObject("far", new string[] {"thest"}, "Value"));
       list.Add(new ListObject("the", new string[] {"ran"}, "Value"));
       list.Add(new ListObject("thest", new string[] {"ran", "the"}, "Value"));

            //What I want the order of the list to become
            /* ran
             * the
             * far
             * thest
             */

        foreach(var o in list) { Console.WriteLine(o.name);}

        var ordered = list
            .OrderBy(o => o.dependencies.Count()) // This is not needed, it's here just to show that you can chain OrderBy
            .ThenBy( o => string.Join(",",o.dependencies));
        Console.WriteLine(">>>Sorted");
        foreach(var o in ordered) { Console.WriteLine(o.name);}

Output:

ran
far
the
thest
>>>Sorted
ran
the
far
thest

Here is a version with the object references instead of strings

    public class ListObject
    {
        public string name { get; }

        public ListObject[] dependencies{get;}

        private object value;
        public ListObject(string name, ListObject[] dependencies, object value)
        {
            this.name = name;
            this.dependencies = dependencies;
            this.value = value;
        }
    }

    public static void Main(string[] args)
    {
        var ran = new ListObject("ran", new ListObject[0], "Value");
        var the = new ListObject("the", new[]{ran}, "Value");
        var thest = new ListObject("thest", new[]{ran, the}, "Value");
        var far = new ListObject("far", new[]{thest}, "Value");

        List<ListObject> list = new List<ListObject>(){ran, the, thest, far};
        //What I want the order of the list to become
        /* ran
             * the
             * far
             * thest
             */
        foreach (var o in list)
        {
            Console.WriteLine(o.name);
        }

        var ordered = list
              .OrderBy(o => o.dependencies.Count()) // This is not needed, it's here just to show that you can chain OrderBy
              .ThenBy(o => string.Join(",", o.dependencies.Select(d => d.name)));
        Console.WriteLine(">>>Sorted");
        foreach (var o in ordered)
        {
            Console.WriteLine(o.name);
        }
    }
tymtam
  • 31,798
  • 8
  • 86
  • 126
  • I am not trying to sort by the name, I am trying to sort by the values in the string array. – Heirteir Oct 17 '19 at 12:36
  • Thank you! I edited the test input to make it more clear what I was asking for. – Heirteir Oct 17 '19 at 12:50
  • Yes, it was a good idea to update it! It became much clearer. – tymtam Oct 17 '19 at 12:50
  • Sorry, actually it isn't solved yet, I edited the question again to make it a bit more clear, this string[] inside the ListObject should be references to other ListObjects – Heirteir Oct 17 '19 at 13:01
  • The sort still gives the expected output. You haven't provided the rules, just the expected output. – tymtam Oct 17 '19 at 13:11
  • the string array can have a random input for example { "the", "ran" } or {"far", "the"} – Heirteir Oct 17 '19 at 13:13
  • what would the order be then? – tymtam Oct 17 '19 at 13:20
  • 1. You've changed the input again. 2. The test code does not contain "test_2" anymore. – tymtam Oct 17 '19 at 13:28
  • ...and now you're deleting your comments :( – tymtam Oct 17 '19 at 13:30
  • Sorry I accidently pressed enter. I updated the original question to once again make it more clear. Sorry for the confusion this is my first time asking a question so I am messing up a bit. I updated the question again. As you can see in the code above the sorting method you posted outputs. ran, the, far, man, thest – Heirteir Oct 17 '19 at 13:33
0

Found the solution to my issue at: http://tawani.blogspot.com/2009/02/topological-sorting-and-cyclic.html

it's known as topological sorting.

Heirteir
  • 21
  • 6