我无法在基于两个字段(JOB_ID和EMPLOYEE_ID)的唯一列表中选择第一项。
每项工作应仅分配给一名雇员(最低工资为OVERALL_SCORE的雇员),然后继续分配下一名雇员。
列表对象如下:
JobMatch.cs
public int JOB_ID { get; set; }
public int JOB_MATCHES_COUNT { get; set; }
EmployeeMatch.cs
public int EMPLOYEE_ID { get; set; }
public int EMPLOYEE_MATCHES_COUNT { get; set; }
Rankings.cs
public int JOB_ID { get; set; }
public int EMPLOYEE_ID { get; set; }
public int TRAVEL_TIME_MINUTES { get; set; }
public int PRIORITY { get; set; }
public int OVERALL_SCORE { get; set; }
Rankings.cs根据旅行时间字段和 员工/工作的匹配数。
EmployeeMatch.cs
+-------------+-------------------+
| EMPLOYEE_ID | EMP_MATCHES_COUNT |
+-------------+-------------------+
| 3 | 1 |
| 4 | 1 |
| 2 | 3 |
| 1 | 4 |
+-------------+-------------------+
JobMatch.cs
+--------+-------------------+
| JOB_ID | JOB_MATCHES_COUNT |
+--------+-------------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 2 |
| 4 | 4 |
+--------+-------------------+
Ranking.cs (简称为不填满屏幕)
+--------+-------------+---------------+
| JOB_ID | EMPLOYEE_ID | OVERALL_SCORE |
+--------+-------------+---------------+
| 4 | 3 | 800 |
| 4 | 4 | 800 |
| 3 | 1 | 800 |
| 3 | 2 | 1200 |
| 2 | 1 | 1600 |
| 2 | 2 | 1800 |
| 4 | 1 | 2000 |
| 4 | 2 | 2100 |
| 1 | 1 | 6400 |
+--------+-------------+---------------+
基本上,我们的想法是在此列表中选择第一个唯一的Employee和Job,然后将最佳匹配项放在一个单独的列表中,类似于上述情况的以下内容:
+--------+-------------+---------------+
| JOB_ID | EMPLOYEE_ID | OVERALL_SCORE |
+--------+-------------+---------------+
| 4 | 3 | 800 |
| 3 | 1 | 800 |
| 2 | 2 | 1800 |
+--------+-------------+---------------+
我尝试了以下操作,但未按预期工作:
var FirstOrder = (rankings.GroupBy(u => u.JOB_ID)
.Select(g => g.First())).ToList();
var SecondOrder = (FirstOrder.GroupBy(u => u.EMPLOYEE_ID)
.Select(g => g.First())).ToList();
答案 0 :(得分:1)
想法是选择第一个元素,然后从列表中删除相应的元素,以确保下一个选择是唯一的,如下所示:
var rankings = new List<Rankings> {
new Rankings{ JOB_ID= 4,EMPLOYEE_ID= 3, OVERALL_SCORE= 800 },
new Rankings{ JOB_ID= 4,EMPLOYEE_ID= 4, OVERALL_SCORE= 800 },
new Rankings{ JOB_ID= 3,EMPLOYEE_ID= 1, OVERALL_SCORE= 800 },
new Rankings{ JOB_ID= 3,EMPLOYEE_ID= 2, OVERALL_SCORE= 1200 },
new Rankings{ JOB_ID= 2,EMPLOYEE_ID= 1, OVERALL_SCORE= 1600 },
new Rankings{ JOB_ID= 2,EMPLOYEE_ID= 2, OVERALL_SCORE= 1800 },
new Rankings{ JOB_ID= 4,EMPLOYEE_ID= 1, OVERALL_SCORE= 2000 },
new Rankings{ JOB_ID= 4,EMPLOYEE_ID= 2, OVERALL_SCORE= 2100 },
new Rankings{ JOB_ID= 1,EMPLOYEE_ID= 1, OVERALL_SCORE= 6400 },
};
var cpy = new List<Rankings>(rankings);
var result = new List<Rankings>();
while (cpy.Count() > 0)
{
var first = cpy.First();
result.Add(first);
cpy.RemoveAll(r => r.EMPLOYEE_ID == first.EMPLOYEE_ID || r.JOB_ID == first.JOB_ID);
}
结果:
+--------+-------------+---------------+
| JOB_ID | EMPLOYEE_ID | OVERALL_SCORE |
+--------+-------------+---------------+
| 4 | 3 | 800 |
| 3 | 1 | 800 |
| 2 | 2 | 1800 |
+--------+-------------+---------------+
答案 1 :(得分:1)
真的,如果您想获得该工作的最高分,则无需按唯一的JOB_ID/EMPLOYEE_ID
进行选择,而需要按JOB_ID/OVERALL_SCORE
进行排序,然后选择第一个每JOB_ID
个匹配的员工(尚未在“分配的列表”中)。
您可以使用LINQ按顺序获取项目:
var sorted = new List<Ranking>
(
rankings
.OrderBy( r => r.JOB_ID )
.ThenBy( r => r.OVERALL_SCORE )
);
...然后剥离想要的员工...
var best = new List<Ranking>( );
sorted.ForEach( r1 =>
{
if ( !best.Any
(
r2 =>
r1.JOB_ID == r2.JOB_ID
||
r1.EMPLOYEE_ID == r2.EMPLOYEE_ID
) )
{
best.Add( r1 );
}
} );
您可以在IComparable<Ranking>
上实现Ranking
,而不是使用Linq 生成排序列表,然后对排名进行排序:
public class Ranking : IComparable<Ranking>
{
int IComparable<Ranking>.CompareTo( Ranking other )
{
var jobFirst = this.JOB_ID.CompareTo( other.JOB_ID );
return
jobFirst == 0?
this.OVERALL_SCORE.CompareTo( other.OVERALL_SCORE ):
jobFirst;
}
//--> other stuff...
}
然后,当您对排名进行排序()时,它们将按JOB_ID / OVERALL_SCORE顺序排列。实现IComparable<Ranking>
可能会更快,并且会占用更少的内存。
请注意,您有问题...可能是一个未声明的目标。找最多的工作更重要...还是为最多的员工找到工作更重要?我选择的路线会按照您的建议去做,只是随您去选择最适合该职位的员工...但是,也许,职位2的 only 员工可能与该职位的最佳员工相同工作1 ...如果您将他/她放到工作1,则可能没有其他人去工作2。这可能会变得很复杂:-)
答案 2 :(得分:0)
基本上,您可以使用System.Linq.Distinct
方法,该方法由自定义相等比较器IEqualityComparer<Ranking>
增强。 System.Linq
开箱即用地提供了此方法。
public class Comparer : IEqualityComparer<Ranking>
{
public bool Equals(Ranking l, Ranking r)
{
return l.JOB_ID == r.JOB_ID || l.EMPLOYEE_ID == r.EMPLOYEE_ID;
}
public int GetHashCode(Ranking obj)
{
return 1;
}
}
这里的技巧是使用GetHashCode
方法,然后像这样简单
rankings.Distinct(new Comparer())