Laden...

Linq lernen - Mit welchem Projekt?

Erstellt von R3turnz vor 8 Jahren Letzter Beitrag vor 8 Jahren 2.222 Views
R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 8 Jahren
Linq lernen - Mit welchem Projekt?

Hallo,
ich habe die Dokumentation nun nochmal gelesen, und mich auch schon mit den Musterdaten ausgetobt.
Jetzt wo eine längere Fahrt ansteht, würde ich LinQ gerne nochmal vertiefen, dazu bräuchte ich halt nur noch ein Projekt, in welchem ich LinQ gut einsetzen könnte. (Kann auch was sehr kleines sein)
Es würde sich halt leider auf LinQ to Objects beschränken, XML und der andere Kram kommt erst später...
Mir ist bewusst das es einen Sammelthread gibt, dort ist mir aber nichts zu diesem Thema ins Auge gefallen...

LG

T
314 Beiträge seit 2013
vor 8 Jahren

Eine ToDo Liste mit Kategorien und weiteren Metadaten, sodass einfaches Suchen und Statistiken möglich sind? (wenn nicht ToDo dann eben ein Haushaltsbuch oder ähnliches)

3.003 Beiträge seit 2006
vor 8 Jahren

So etwas in der Art von eddb eignet sich ziemlich gut. In dem konkreten Fall (ich schlage nicht vor, dass du das nachprogrammierst, wozu auch) hat man eine Liste von Sternensystemen, eine Liste von Stationen, sowie u.a. eine Liste von den Preisen auf den jeweiligen Stationen. Das sind eine Menge Informationen, die sich auf verschiedene Weise sinnvoll abfragen lassen: Routenberechnung von System A nach System B, Handelsroutenberechungen, Sortieren nach "lohnenden" Handelsrouten, Suche nach Stationen / System mit bestimmten Gütern oder Ausstattungen und so weiter und so fort. Das schöne in dem Beispiel ist, dass die Daten frei zur Verfügung stehen und sehr umfangreich sind. Nach dem deserialisieren dieser Daten kann man dann mit Linq jeden Unfug drauf veranstalten, der einem einfällt. Such dir also irgendetwas, das dir einen möglichst umfangreichen und komplexen Satz an Daten hergibt, und arbeite damit. Anderes Beispiel: Kraftstoffpreise sind seit 2013 theoretisch durch jeden abfragbar, praktisch muss man dafür leider etwas Bürokratie überwinden. Allerdings gibt es einige Stellen, die die Rohdaten zur Verfügung stellen - such mal nach "Benzinpreis" und "API".

Es finden sich sicherlich noch etliche andere Datenquellen mit praktischem Bezug.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 8 Jahren

@LaTino Hört sich sehr intressant an, ich spiele nämlich Elite:Dangerous, aber konnte mich bisher nie fürs Handeln begeistern, weil mir einfach die Routen fehlen... So kann ich sie mir einfach berechnen lassen 😉
Habe aber noch eine Frage: Wie soll ich die Datein deseralisieren. Ich habe schon folgendes gefunden:
https://msdn.microsoft.com/de-de/library/bb908625%28v=vs.110%29.aspx
Ich brauche aber auch noch die Klassen dazu, ich kann ein paar Eigenschaften aus der Datei rauslesen, jedoch halt nicht alle...

LG

3.003 Beiträge seit 2006
vor 8 Jahren

Forumssuche benutzen: http://www.mycsharp.de/wbb2/search.php?searchid=993548

Wäre in dem Fall ein reines Übungsprojekt, eddb selbst hat schon recht weitreichende Funktionen, nur eben nicht "selbst gemacht" 😉

LaTino
Edit: völlig vergessen, dass man die Forensuche nicht direkt verlinken kann - sorry: Forumssuche nach Deserialisieren JSON

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 8 Jahren

Ich poste es jetzt hier, neuer Thread lohnt sich doch nicht:
Ich habe am Anfang probiert mit dem DataContractJsonSerializer zu Arbeiten, hier habe ich aber überhaupt nicht durchgeblickt... Naja hätte ich denn ersten Treffer der Suche besser gelesen, wäre ich früher auf Json.NET gestoßen, meine Methode sieht gerade so aus:


public class JsonLoader<T>
    {
        
        //Habe keinerlei Exception-Handling, 
        public List<T> Load(string jsonpath)
        {
            List<T> output = new List<T>(10);
            FileInfo jsonfileinfo = new FileInfo(jsonpath);
            if (!jsonfileinfo.Exists) return null;
            using (var jsonread = new JsonTextReader(jsonfileinfo.OpenText()))

            {
                var settings = new JsonSerializerSettings();
                settings.NullValueHandling = NullValueHandling.Include;
                JsonSerializer serializer = JsonSerializer.Create(settings);
                while(jsonread.Read())
                {
                 output.Add(serializer.Deserialize<T>(jsonread));
                }
            }
            return output;
        }
    } 
}

Die Klassen habe ich von json2csharp:


    public class ModuleGroup
        {
            public int id { get; set; }
            public int category_id { get; set; }
            public string name { get; set; }
            public string category { get; set; }
        }
   
        public class Module
        {
            public int id { get; set; }
            public int group_id { get; set; }
            public int @class { get; set; }
            public string rating { get; set; }
            public int? price { get; set; }
            public string weapon_mode { get; set; }
            public int? missile_type { get; set; }
            public string name { get; set; }
            public int? belongs_to { get; set; }
            public string ship { get; set; }
            public ModuleGroup group { get; set; }
            public double? mass { get; set; }
            public int? dps { get; set; }
            public double? power { get; set; }
            public int? damage { get; set; }
            public int? ammo { get; set; }
            public double? range_km { get; set; }
            public string efficiency { get; set; }
            public double? power_produced { get; set; }
          public int? duration { get; set; }
        public int? cells { get; set; }
        public string recharge_rating { get; set; }
        public int? capacity { get; set; }
       
        public int? count { get; set; }
       
        public int? range_ls { get; set; }
        
        public int? rate { get; set; }
        
        public int? bins { get; set; }
   
        public int? additional_armour { get; set; }
   
        public int? vehicle_count { get; set; }
        }
           public class System
        {
   
        public int id { get; set; }
      
        public string name { get; set; }
       
        public double x { get; set; }
      
        public double y { get; set; }
       
        public double z { get; set; }
      
        public string faction { get; set; }
       
        public long? population { get; set; }
       
        public string government { get; set; }
        
        public string allegiance { get; set; }
       
        public string state { get; set; }
        
        public string security { get; set; }
        
        public string primary_economy { get; set; }
      
        public string power { get; set; }
       
        public string power_state { get; set; }
      
        public int? needs_permit { get; set; }
        
        public int updated_at { get; set; }
        
        public string simbad_ref { get; set; }
        }
   
        public class Stations
        {
       
        public int id { get; set; }
       
        public string name { get; set; }
        public double x { get; set; }
      
        public double y { get; set; }
      
        public double z { get; set; }
        
        public string faction { get; set; }
        
        public long? population { get; set; }
        
        public string government { get; set; }
       
        public string allegiance { get; set; }
        
        public string state { get; set; }
        
        public string security { get; set; }
       
        public string primary_economy { get; set; }
       
        public string power { get; set; }
      
        public string power_state { get; set; }
       
        public int? needs_permit { get; set; }
       
        public int updated_at { get; set; }
       
        public string simbad_ref { get; set; }
        }

Nach einer gefühlten Ewigkeit wollte ich mein Code testen:


 static void Main()
        {
            JsonLoader<Elite_Dangerous_Tool.System> systemloader = new JsonLoader<Elite_Dangerous_Tool.System>();
            foreach(var loadedsystem in systemloader.Load("C:\\\\Users\\Name\\Desktop\\Elite Dangerous-Sternensystem\\systems.json"))
            {
                Console.WriteLine(loadedsystem.ToString());
            }
            Console.ReadKey();
        }

Es wird folgende Exception geschmießen:> Fehlermeldung:

Ein Ausnahmefehler des Typs "Newtonsoft.Json.JsonSerializationException" ist in Newtonsoft.Json.dll aufgetreten.

Zusätzliche Informationen: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Elite_Dangerous_Tool.System' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.

Path '', line 1, position 1.

Wenn ich das richtig verstehe, weißt er mich darauf hin, er hätte ein Array gefunden, und ich solle doch bitte eine Collection in meiner Klasse hinzufügen. Ich kann aber beim besten willen weder in der Json noch in der Klasse eine Auflistung finden:

{"id":17,"name":"10 Ursae Majoris","x":0.03125,"y":34.90625,"z":-39.09375,"faction":"NoneNone","population":0,"government":"None","allegiance":"None","state":"None","security":"Low","primary_economy":"None","power":"None","power_state":null,"needs_permit":0,"updated_at":1455744292,"simbad_ref":"10 Ursae Majoris"

Ich habe es wirklich probiert zu lösen. Es scheint aber irgendwie ein Array zu geben was ich nicht finden kann...
Wahrscheinlich müsste ich mich in Json einarbeiten, ich will aber gerade einfach nur meine Objekte haben, um mit LinQ arbeiten zu können... Ich hoffe das ist verständlich.

LG

16.834 Beiträge seit 2008
vor 8 Jahren

Bitte gewöhn Dir die C# Richtlinien an, was gerade zB die Groß-Kleinschreibung von Klassen und Eigenschaften angeht.
[Artikel] C#: Richtlinien für die Namensvergabe

Das ist echt nicht bequem zu lesen....

      List<T> output = new List<T>(10);

Warum hier fix 10? Sinn?

Macht es sinn, dass alle Deine Eigenschaften Strings sind?
Warum ist Category nicht zB. eine Klasse, die Name und ID inne hat?
Dafür ist doch OOP gedacht! 🤔

3.003 Beiträge seit 2006
vor 8 Jahren

a) ja, an die NewtonSoft-Json-Geschichte hatte ich eigentlich gedacht
b) alles, was Abt sagt, leicht eingeschränkt die Sache mit den Strings. Aber prinzipiell warst du schon mal weiter mit OOP.
c) Beispiel:


//systems
//{"id":17,"name":"10 Ursae Majoris","x":0.03125,"y":34.90625,"z":-39.09375,"faction":"NoneNone","population":0,"government":"None","allegiance":"None",
//"state":"None","security":"Low","primary_economy":"None","power":"None","power_state":null,"needs_permit":0,"updated_at":1455744292,"simbad_ref":"10 Ursae Majoris"}
[JsonObject(MemberSerialization.OptIn)]
public class System
{
    private List<Station> _stations;

    [JsonProperty("id", Required = Required.Always, Order=1)]   
    public int Id { get; set; }
    [JsonProperty("name", Required = Required.Always, Order=2)]   
    public string Name { get; set; }
    [JsonProperty(Order=3)]   
    public GalaxyCoordinate Coordinate { get; set; }
    [JsonProperty("faction", Required = Required.AllowNull, Order=4)]   
    public string Faction { get; set; }
    [JsonProperty("population", Required = Required.AllowNull, Order=5)]   
    public long? Population { get; set; }
    [JsonProperty("government", Required = Required.AllowNull, Order=6)]   
    public string Government { get; set; }
    [JsonProperty("allegiance", Required = Required.AllowNull, Order=7)]   
    public string Allegiance { get; set; }
    [JsonProperty("state", Required = Required.AllowNull, Order=8)]   
    public string State { get; set; }
    [JsonProperty("security", Required = Required.AllowNull, Order=9)]   
    public string Security { get; set; }
    [JsonProperty("primary_economy", Required = Required.AllowNull, Order=10)]  
    public string PrimaryEconomy { get; set; }
    [JsonProperty("power", Required = Required.Always, Order=11)]  
    public string Power { get; set; }
    [JsonProperty("power_state", Required = Required.AllowNull, Order=12)]  
    public string PowerState { get; set; }
    [JsonProperty("needs_permit", Required = Required.AllowNull, Order=13)]  
    public int? Permission { get; set; }
    [JsonProperty("updated_at", Required = Required.Always, Order=14)]  
    [JsonConverter(typeof(UnixTimestampConverter))]
    public DateTime UpdatedAt { get; set; }
    [JsonProperty("simbad_ref", Required = Required.AllowNull, Order=15)]  
    public string SimbadReference { get; set; }

    public override string ToString()
    {
        return string.Format(@"System ""{0}""@{1}", Name, Coordinate);
    }
}


//JsonConverter, weil ich die Koordinaten unbedingt als eigene Klasse wollte.
public class SystemConverter : JsonConverter, IProgressable
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var system = (System)value;
        var jsonObject = JObject.FromObject(value);
        var jsonProperty = jsonObject.Children<JProperty>().First(p => p.Name == "Coordinate");
        jsonProperty.AddAfterSelf(new JProperty("z", system.Coordinate.Z));
        jsonProperty.AddAfterSelf(new JProperty("y", system.Coordinate.Y));
        jsonProperty.AddAfterSelf(new JProperty("x", system.Coordinate.X));

        jsonProperty.Remove();
        jsonObject.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);
        var result = new System();
        serializer.Populate(jsonObject.CreateReader(), result);
        result.Coordinate = new GalaxyCoordinate
        {
            X = jsonObject.Children<JProperty>().First(p => p.Name == "x").Value.ToObject<double>(),
            Y = jsonObject.Children<JProperty>().First(p => p.Name == "y").Value.ToObject<double>(),
            Z = jsonObject.Children<JProperty>().First(p => p.Name == "z").Value.ToObject<double>()
        };
        return result;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(System);
    }
}


//Beispiel für die Deserialisierung
var serializerSettings = new JsonSerializerSettings();
var systemConverter = new SystemConverter();

serializerSettings.Converters.Add(systemConverter);

_systems = JsonConvert.DeserializeObject<System[]>(File.ReadAllText(systemsFilename), serializerSettings); //systemsfilename ist daann systems.json oder whatever

Ist an sich nur viel Tipparbeit.
(EDIT: bisschen Coderauschen entfernt. Faction, Government, Allegiance, Security, Power, PrimaryEconomy, Permission, PowerState sollten eigentlich keine Strings sein. Kann man aber temporär machen.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 8 Jahren

Bei den 10 war mein Gedanke das von mindestens 10 (eher 100 oder 1000) Elementen auszugehen ist, und so nicht so oft das interne Array kopiert werden muss. Wahrscheinlich hätten es dann doch eher 100 oder 1000 seien müssen, und die Performance steigt wahrscheinlich auch nicht merklich...
Die Klassen habe ich wie bereits erwähnt von json2csharp, diese sind also generiert, ich wusste nicht das diese "qualitative" Nachteile haben.

An sich habe ich mir zu wenig Mühe mit der Deseralisierung gegeben, ich wollte mich da ehrlich gesagt nur schnell durch kommen, um eigentlich Anfangen zu können.

@LaTino Danke für den Code, werde ihn erstmal anschauen und dann für die Module und Stationen umschreiben. Ich würde bei den strings auf Enums setzen, sind ja alles auf einschränkbare Möglichkeiten bezieht.

16.834 Beiträge seit 2008
vor 8 Jahren

, und die Performance steigt wahrscheinlich auch nicht merklich...

Lass mal Performance-Optimierungen aus Deinen Gedanken raus. Soweit bist noch nicht - und um Performance kümmert man sich immer erst wenn es auch notwendig ist: keep it simple, stupid.

Ich hab noch nie jemand gesehen, der hier einen initialen Wert setzt.

ich wollte mich da ehrlich gesagt nur schnell durch kommen, um eigentlich Anfangen zu können.

Bringt aber nichts, wenn Du es nicht verstehst 😉

R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 8 Jahren

@LaTino Nur aus Intresse: Deine Klasse implemntiert ein Interface IProgressable. Ich kann dazu nichts finden, also muss es von dir sein. Was für einen Sinn hat es.? Ich würde auf eine Art Fortschritsangabe tippen, aber du scheinst es nirgends zu verwenden.

3.003 Beiträge seit 2006
vor 8 Jahren

Ah, das gehört zu dem Coderauschen, von dem ich sprach. Nimm's raus, tut nix. (ist eine Schnittstelle, die das Laden im Hintergrund ermöglicht und Fortschrittsmeldungen macht, für einen Ladebalken...weil das Laden der Systeme, Stationen, Preise etc. schon ein bisschen dauern kann).

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)