Solved

LINQ help

Posted on 2014-10-03
10
146 Views
Last Modified: 2016-02-15
Hi, I thought I understood LINQ.

I do not.

Below is some code I have written to try to get a distinct list of strings. It doesn't even compile. Can someone please help me get it right?

Thank you

John

using System;
using System.Linq;

namespace ConsoleApplication41
{
    public class Test0
    {
        public String[] Names { get; set; }
        public int id { get; set; }
    }

    public class Test1
    {
        public Test0[] Tests { get; set; }
        public int group { get; set; }
    }

    class Program
    {
        private void LinqTest()
        {
            Test0 test011 = new Test0 { Names = new String[] { "one", "two", "three" } };
            Test0 test012 = new Test0 { Names = new String[] { "three", "four" } };
            Test0 test013 = new Test0 { Names = new String[] { "ten", "one" } };
            Test1[] test1 = new Test1[] {new Test1 { Tests = new Test0[] { test011, test012, test013 } } };

            // Some magic LINQ to give me 
            // one, two, three, four, ten
            // from test1
            //
            // THE FOLLOWING DOESN'T WORKa
            var allTest1s = (
                                from y
                                    in (from x
                                           in test1
                                         select x.Tests
                                       )
                                select y.Names
                            ).ToArray<String>().Distinct<String>();
        }

        static void Main(string[] args)
        {
            Program program = new Program();
            program.LinqTest();
        }
    }
}

Open in new window

0
Comment
Question by:John Bolter
  • 4
  • 3
  • 3
10 Comments
 
LVL 22

Expert Comment

by:p_davis
ID: 40360285
what is the error/errors you are getting, when compiling.... seems x.Tests should be casted??
0
 

Author Comment

by:John Bolter
ID: 40360297
Hi, I struggled with that too.

I tried

            var allTest1s = (
                                from y
                                    in (from x
                                           in test1
                                         select ((Test0[])x.Tests)
                                       )
                                select y
                            ).ToArray<Test0>().Distinct<String>();

Open in new window


but then I couldn't convert all the Test0's to their Names Strings so I'm sort of missing an inner loop or something.
0
 
LVL 22

Expert Comment

by:p_davis
ID: 40360312
what errors are you getting?
0
Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

 

Author Comment

by:John Bolter
ID: 40360326
The error is it doesn't compile. This is what I think my LINQ query should look like but it is clearly wrong.

The compile error is

Error	1	Instance argument: cannot convert from 'System.Collections.Generic.IEnumerable<ConsoleApplication41.Test0[]>' to 'System.Collections.Generic.IEnumerable<ConsoleApplication41.Test0>'	c:\users\johneb\documents\visual studio 2013\Projects\ConsoleApplication41\ConsoleApplication41\Program.cs	39	30	ConsoleApplication41
Error	2	'System.Collections.Generic.IEnumerable<ConsoleApplication41.Test0[]>' does not contain a definition for 'ToArray' and the best extension method overload 'System.Linq.Enumerable.ToArray<TSource>(System.Collections.Generic.IEnumerable<TSource>)' has some invalid arguments	c:\users\johneb\documents\visual studio 2013\Projects\ConsoleApplication41\ConsoleApplication41\Program.cs	39	30	ConsoleApplication41

Open in new window

0
 
LVL 22

Expert Comment

by:p_davis
ID: 40360329
what happens if, in the select, you get rid of the cast (Test0[])
0
 

Author Comment

by:John Bolter
ID: 40360338
It still doesn't compile. I only added the cast because you suggested it above.

Try it. The whole program can be copy/pasted into Visual Studio
0
 
LVL 33

Accepted Solution

by:
it_saige earned 500 total points
ID: 40360355
I think this is what you are after:
			var allTest1s = (from testGroup in test1
						  from test in testGroup.Tests
						  from name in test.Names
						  select name).Distinct();

Open in new window


-saige-
0
 
LVL 33

Expert Comment

by:it_saige
ID: 40360359
Using:
using System;
using System.Linq;

namespace LinqExample
{
	class Test0
	{
		public string[] Names { get; set; }
		public int Id { get; set; }
	}

	class Test1
	{
		public Test0[] Tests { get; set; }
		public int Group { get; set; }
	}

	class Program
	{
		static void Main(string[] args)
		{
			Test0 test011 = new Test0() { Names = new string[] { "one", "two", "three" } };
			Test0 test012 = new Test0() { Names = new string[] { "three", "four" } };
			Test0 test013 = new Test0() { Names = new string[] { "ten", "one" } };
			Test1[] test1 = new Test1[] { new Test1() { Tests = new Test0[] { test011, test012, test013 } } };

			var allTest1s = (from testGroup in test1
						  from test in testGroup.Tests
						  from name in test.Names
						  select name).Distinct();

			foreach (var test in allTest1s)
				Console.WriteLine(test);
			Console.ReadLine();
		}
	}
}

Open in new window

Produces the following output:Capture.JPG
-saige-
0
 

Author Closing Comment

by:John Bolter
ID: 40360361
I see how you've done it now, I didn't realise you could have two "from" like that. I was thinking in a sort of SQL way where that isn't a valid syntax.
Thank you
0
 
LVL 33

Expert Comment

by:it_saige
ID: 40360370
When you really think about it it makes sense.

test1 represents an array of Test1, so you enumerate over each Test1.
Inside of each Test1 you have an array of Test0's, represented as Tests, so you have to enumerate over each Test0.
Then inside of each Test0, you have an array of strings, represented as Names, so you have to enumerate over each Name.

-saige-
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

685 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question