tags:

views:

170

answers:

4

I have this class

public class Line
{
  public string ConnectionsIndex{get;set;}
}

my Linq problem is that I have to aggregate these Lines

var l1 = new Line{ ConnectionsIndex="01,02"};
var l2 = new Line{ ConnectionsIndex="02,03"};
var l3 = new Line{ ConnectionsIndex="01,03"};

into this

var l4 = new Line{ ConnectionsIndex="01,02,03"};

It's possible to do with Linq?

DETAIL:

The thing is more complicate (at least for me) when I add the other items that I have in my collection.

var l5 = new Line (ConnectionsIndex = "02,04"); 
var l6 = new Line (ConnectionsIndex = "03,06");

because do not exist other lines with the pairs 03,04 , 01,04 , 01,06 and 02,06

I do not know if I have explained it well ...

in practice, imagine you have all the points of a polygon, I want to get a line of all the items from the query by giving a list of connections between all points of each polygon.

(my list contains more than one polygon)

One point should not be included in result if not connected to all others.

This is an example of my list content:

ConnectionsIndex="166,171"
ConnectionsIndex="166,174"
ConnectionsIndex="166,333"
ConnectionsIndex="169,170"
ConnectionsIndex="171,175"
ConnectionsIndex="171,334"
ConnectionsIndex="167,174"
ConnectionsIndex="172,174"
ConnectionsIndex="174,335"
ConnectionsIndex="177,341"
ConnectionsIndex="180,200"
ConnectionsIndex="181,183"
ConnectionsIndex="182,199"
ConnectionsIndex="184,185"
ConnectionsIndex="186,188"
ConnectionsIndex="189,192"
ConnectionsIndex="190,230"
ConnectionsIndex="191,375"

In this List you have for example a triangle between 166, 171 and 334

More detail:

var group = lines.Where(x => x.ConnectionsIndex.Split(',').Contains(line. ConnectionsIndex.Split(',')[0]) || x. ConnectionsIndex.Split(',').Contains(line. ConnectionsIndex.Split(',')[1])).ToList(); if (group.Count()==1) { straight_lines.Add(line); } else { //Here I have a "group" with all the lines between point.. I want to get distinc points }

+1  A: 

Something like:

var connections = (from line in lines
                   from connection in line.Split(',')
                   select connection).Distinct()
                                     .ToArray();

Line line = new Line { ConnectionsIndex = string.Join(",", connections) };

This doesn't order the connections, but you can easily add that if you need it.

This would all be cleaner if you were happy to have ConnectionsIndex as a collection of strings instead of a single delimited string, of course :)

Jon Skeet
I must have it in form of single delimited string to save it easly with NHibernate... i'll check soon your hint.
Mauro Destro
Sorry, but it's not the right answer... I have to edit my question and add more detail..
Mauro Destro
A: 

I used this:

var l4 = new Line{ 
    ConnectionsIndex = 
        string.Join(",", (lines.SelectMany(x => x.ConnectionsIndex.Split(','))
                               .Distinct()
                               .OrderBy(s => s)).ToArray())
};
Botz3000
No sorry, but it return the same results as the Jon Skeet one's
Mauro Destro
A: 

This is the bad way I have found... and it works!

var l = linee.Distinct(
            (a, b) => a.ConnectionsIndex == b.ConnectionsIndex,x=>x.ConnectionsIndex.GetHashCode())
        .ToList();

    var single_lines = new List<Linea>();
    var multiple_lines = new List<Linea>();
    foreach (var linea in l)
    {
        var group = l
            .Where(x => x.ConnectionsIndex.Split(',').Contains(linea.ConnectionsIndex.Split(',')[0]) ||
                x.ConnectionsIndex.Split(',').Contains(linea.ConnectionsIndex.Split(',')[1])).ToList();
        if (group.Count()==1)
        {
            single_lines.Add(linea);
        }
        else
        {
            var indexes = new List<string>();
            var dist = group.Select(x => new {Index = x.ConnectionsIndex.Split(',').ToList()}).ToList();    

            foreach (var linea1 in dist)
            {
        indexes=indexes.Concat(linea1.Index).ToList();
            }

            var indexstring = new StringBuilder();
            foreach (var s in indexes.Distinct().OrderBy(x=>Convert.ToInt32(x)))
            {
        indexstring.Append(s).Append(',');
            }
            indexstring.Remove(indexstring.Length - 1, 1);
            multiple_lines.Add(new Linea() {ConnectionsIndex = indexstring.ToString()});
        }
    }

var multi_distinct=multiple_lines.Distinct(
            (a, b) => a.ConnectionsIndex == b.ConnectionsIndex, x => x.ConnectionsIndex.GetHashCode())
            .ToList();

linee = single_lines.Concat(multi_distinct).ToList();

If you find or known better solutions, you are welcome!

Mauro Destro
A: 

Just a note that I think what you're asking for is a way to find maximal cliques (a concept from graph theory). This is known to be an NP-Hard problem. I think your version will work sometimes, and hopeflly for those cases you're interested in. But, not for complicated cases where anything may be connected to anything else. Indeed, if you have a lot of nodes, those cases aren't feasible, even with large CPU cycle budgets (regardless of LINQ).

RD1