private void GenerateButton_Click(object sender, RoutedEventArgs e) { var listRand = new ListRand(); // Let's have some fun with TPL var nums = Enumerable.Range(0, NODES_COUNT-1).ToArray(); // Just a balanced partitioner var partitioner = Partitioner.Create(nums, true); var nodes = partitioner.AsParallel().Select(i => { var newNode = new ListNode { Id = Guid.NewGuid(), Data = string.Format("Node{0} Data", i) }; return newNode; }).ToList(); var rand = new Random(Environment.TickCount); ListNode previous = null; foreach (var node in nodes) { node.Previous = previous; node.Random = nodes[rand.Next(0, nodes.Count)]; if (previous != null) { previous.Next = node; } previous = node; } listRand.Count = nodes.Count; listRand.Head = nodes.First(); listRand.Tail = nodes.Last(); _lastListRand = listRand; PrintList(listRand, GeneratedListTextBox); }
// Changed to just a stream to make it possible to deserialize from memory stream public void Deserialize(Stream stream) { // Again, we do not going to manage the stream here since it was initialized somewhere outside. // The only we can do here is to catch the errors while reading to rethrow with meaningful message. var reader = new StreamReader(stream); var serializedString = reader.ReadToEnd(); // Just a simple regex matching the pattern like //'Id:a5c2e13e-85af-40b8-9633-4c9e1c001f62;Prev:00000000-0000-0000-0000-000000000000;Next:59bee4b3-645c-4184-9502-508d5d23096d;Rand:59bee4b3-645c-4184-9502-508d5d23096d;Data:Node1 Data' var regex = new Regex(@"((Id:[;:\w\d\s-]+?);[\s])", RegexOptions.Multiline); var nodeStrings = new List<string>(); var matches = regex.Matches(serializedString).OfType<Match>(); foreach (var match in matches) { // Groups[0] - whole match; Groups[1] - outer group (equal to whole match; seems redundant); Groups[2] - w/o trailing ';' and linebreak var matchWithoutTrailingSemicolon = match.Groups[2].Value; nodeStrings.Add(matchWithoutTrailingSemicolon); } var nodes = new List<ListNode>(nodeStrings.Count); // Creating the cross nodes references Dixtionary. Using the Tuple for simplicity // Assuming the Tuple of Previous; Next; Random node ids var references = new Dictionary<Guid, Tuple<Guid, Guid, Guid>>(); // Just a simple Regex to extract field values var idRegex = new Regex("Id:(.+?);"); var prevRegex = new Regex("Prev:(.+?);"); var nextRegex = new Regex("Next:(.+?);"); var randRegex = new Regex("Rand:(.+?);"); var dataRegex = new Regex("Data:(.+?)$"); nodeStrings.ForEach(ns => { // I know it is BAD to not check IsMatch and Groups count // It is not needed in case of such simple task. Just ommiting the flood of If... Else. var id = Guid.Parse(idRegex.Match(ns).Groups[1].Value); var prevId = Guid.Parse(prevRegex.Match(ns).Groups[1].Value); var nextId = Guid.Parse(nextRegex.Match(ns).Groups[1].Value); var randId = Guid.Parse(randRegex.Match(ns).Groups[1].Value); var data = dataRegex.Match(ns).Groups[1].Value; nodes.Add(new ListNode { Id = id, Data = data }); references.Add(id, new Tuple<Guid, Guid, Guid>(prevId, nextId, randId)); }); nodes.ForEach(n => { // There should be a value with given Id in Dictionary // For safety we can add a check and skip if there no value in Dictionary var reference = references[n.Id]; // If Previous Id is Guid.Empty, then this node is a head and Previous reference should be void if (reference.Item1 != Guid.Empty) { n.Previous = nodes.Single(o => o.Id == reference.Item1); } else { // Assign the Head reference here this.Head = n; } // If Next Id is Guid.Empty, then this node is a Tail and Previous reference should be void if (reference.Item2 != Guid.Empty) { n.Next = nodes.Single(o => o.Id == reference.Item2); } else { // Assign the Tail reference here this.Tail = n; } n.Random = nodes.Single(o => o.Id == reference.Item3); }); this.Count = nodes.Count; }