2017-02-11 5 views
1

У меня есть единственный список объектов, из которых я хочу сделать уникальные комбинации.Как эффективно получить уникальные комбинации списка объектов

Объекты, которые у меня есть (CityObj);

public string City_Name; 
public int Population; 
double xcord; 
double ycord; 
double zcord; 

Результатом будет список, который содержит новый объект (CityComboObj)

public string City_NameA; 
public int PopulationA; 
double xcordA; 
double ycordA; 
double zcordA; 
public string City_NameB; 
public int PopulationB; 
double xcordB; 
double ycordB; 
double zcordB; 

Образец набора данных следующим образом;

  • City1 | 3840 | 42 | -12 | 5
  • City2 | 39402 | 1 | 59 | -5
  • Город3 | 5934 | 99 | -55 | 3
  • City4 | 12394 | -56 | 9 | 16

Результирующий список объектов будет выглядеть;

City1 | 3840 | 42 | -12 | 5 City2 | 39402 | 1 | 59 | -5

City1 | 3840 | 42 | -12 | 5 Город3 | 5934 | 99 | -55 | 3

City1 | 3840 | 42 | -12 | 5 Город4 | 12394 | -56 | 9 | 16

City2 | 39402 | 1 | 59 | -5 Город3 | 5934 | 99 | -55 | 3

City2 | 39402 | 1 | 59 | -5 Город4 | 12394 | -56 | 9 | 16

City3 | 5934 | 99 | -55 | 3 Город4 | 12394 | -56 | 9 | 16

Как вы можете видеть только его уникальные результаты.

В настоящее время я использую ужасно неэффективный apporach, чтобы делать это;

foreach (var element in CityListA) 
      { 
      if (!CityListB.Any(o => o.City_NameA == element.City_NameA && o.City_NameB == element.City_NameB)) 
       { 
        if (!CityListB.Any(o => o.City_NameA == element.City_NameB && o.City_NameB == element.City_NameA)) 
        { 
         CityListB.add(element) 
        } 
       } 
      } 

В двух словах подход должен принять два списка один полный и один пустой, сравнить каждый элемент полного списка с пустым списком, чтобы увидеть, если она существует, или транспонированная существует, и если он не добавляет Это.

Он работает, но он медленный, есть ли лучший способ сделать это?

Thanks

+0

Вы можете объединить 'Any' вызовы, для одного. – Abion47

+0

Как насчет запуска с 'if (! CityListB.Any (o => (o.City_NameA == element.City_NameA && o.City_NameB == element.City_NameB) || (o.City_NameA == element.City_NameB && o.City_NameB == element.City_NameA))) 'так что вы не зацикливаете дважды? –

+0

Ваша проблема: «У меня есть последовательность уникальных элементов длины n. Я хочу сгенерировать все подпоследовательности длины k <= n". Я написал серию статей о различных методах, чтобы сделать это. Серия начинается здесь: https://ericlippert.com/2014/10/13/producing-combinations-part-one/ Но если вас не интересует теория и вы просто хотите код, она здесь: https: // gist.github.com/ericlippert/69c9e93b366f8cc5d6ac –

ответ

1
Your code needs some reengineering, for example: 

internal class CityObjs : List<CityObj> 
{ 
} 

internal class CityObj 
{ 
    public string City_Name; 
    public int Population; 
    double xcord; 
    double ycord; 
    double zcord; 
} 

internal class CityComboObj 
{ 
    internal CityObj CityA ; 
    internal CityObj CityB ; 
    internal CityComboObj(CityObj A,CityObj B) { CityA=A ; CityB=B;} 
} 

internal class CityComboObjs: List<CityComboObj> 
{ 
} 

Предполагая, что список CityObjs инициализируется:

CityComboObjs = new CityComboObjs() ; 
for (int i=0;i<CityObjs.Count-1;i++) for (int j=i+1;j<CityObjs.Count;j++) 
    CityComboObjs.Add(new CityComboObj(CityObjs[i],CityObjs[j]) ; 
+0

Спасибо, в конечном итоге это сделало то, что я искал, и на долю времени (и процессора). –

0

Это действительно работает. Просто замените простые целые числа на реальные объекты. Идея этого кода состоит в том, чтобы сделать это более эффективно, как вы просили, не проверяя, существует ли пара.В вашем случае myList[i] возвратит CITY объект

using System; 
using System.Linq; 
using System.Collections.Generic; 

public class Program 
{ 
    public static void Main() 
    { 
     var myList = (new []{1 , 2, 3, 4}).ToList(); 
     var newList = new List<ListObject>(); 
     var count = myList.Count; 

     for (int i = 0; i < count - 1; i++) 
     {   
      for(int j = i + 1; j < count; j++) 
      { 
       newList.Add(new ListObject(){ I = myList[i], J = myList[j]}); 
      } 
     } 
     newList.ForEach(x => Console.WriteLine(x)); 
    } 

    class ListObject 
    { 
     public int I {get; set;} 
     public int J {get; set;} 

     public override string ToString() 
     { 
      return I + " - " + J; 
     } 
    } 
} 

Выход
1 - 2
1 - 3
1 - 4
2 - 3
2 - 4
3 - 4