提问人:pinkRobot435 提问时间:2/19/2023 更新时间:2/19/2023 访问量:70
根据对象属性值对对象进行排序时出现问题
Problem sorting objects based on value of its properties
问:
我坐在这里,有一个我似乎无法弄清楚的学校项目;我将创建一个控制台应用程序,让用户为一家假设的公司输入一些销售人员。有关销售人员的信息包括他们的姓名、地区和销售商品的数量。然后,根据销售商品的数量将销售人员分为不同的级别。最后,销售人员将被打印到控制台上。打印应该在一次一级进行,例如,如果两个销售人员达到一级,一个达到二级,控制台应如下所示:
John Johnsson, someDistrict, 已售出 33 件商品 Mary Mara, someOtherDistrict, 已售出 40 件商品 2名业务员达到1级
Judy Juggernut,另一个区,售出 67 件商品 1名业务员达到2级
正是有问题的打印部分给我带来了麻烦。当用户输入信息时,将创建推销员类的新对象并将其存储在推销员数组中。然后检查每个推销员的销售商品数量,并为每个推销员分配一个级别。然后使用 bubblesort 对数组进行排序,以使销售人员在 salesmanArray[0] 上销售量最少,依此类推。
在将结果打印到控制台之前,一切正常。我试图为它编写一个方法:
public static void sortering(Salesman[] salesmenArray)
{
Salesman[] level1 = new Salesman[salesmenArray.Length];
Salesman[] level2 = new Salesman[salesmenArray.Length];
Salesman[] level3 = new Salesman[salesmenArray.Length];
Salesman[] level4 = new Salesman[salesmenArray.Length];
for (int i = 0; i < salesmenArray.Length - 1; i++)
{
if (salesmenArray[i].level == 1)
{
level1[i] = salesmenArray[i];
} else if (salesmenArray[i].level == 2)
{
level2[i] = salesmenArray[i];
} else if (salesmenArray[i].level == 3)
{
level3[i] = salesmenArray[i];
} else if (salesmenArray[i].level == 4)
{
level4[i] = salesmenArray[i];
}
}
if (level1.Length != 0)
{
for (int i = 0; i < level1.Length - 1; i++)
{
Console.WriteLine("Name: " + level1[i].name);
Console.WriteLine("District: " + level1[i].district);
Console.WriteLine("Items sold: " + level1[i].itemsSold);
}
Console.WriteLine("" + (level1.Length - 1) + " sellers have reached level 1");
}
//Same thing for level 2, 3 and 4
}
我正在尝试做的是用于不同级别的 4 个新数组。然后,我与所有销售人员一起遍历阵列,并根据销售商品的数量将销售人员放入阵列中。然后,我检查level数组是否为空。如果不是,我会循环播放它们,打印出每个推销员的姓名、地区和销售的物品。最后,还要打印出每个级别有多少卖家。运行程序时,我收到一个错误
Console.WriteLine("Name: " + level1[i].name);
说“System.NullReferenceException已被抛出”对象引用未设置为实例(如果是对象)。
我认为这意味着 level1[i].name 没有引用对象,但我真的不知道如何从那里开始......任何建议或指示将不胜感激!
答:
您得到一个,因为您正在使用与 salesmen 数组相同的长度初始化 level 数组,但您只是根据他们的级别将 salesmen 添加到级别数组中。System.NullReferenceException
因此,level 数组中不会有初始化的元素,当您尝试访问 null 元素的 name 属性时,由于您尝试读取 absent 元素的属性,因此会出现异常。null
要解决此问题,您可以使用代替 .List<T>
是一个通用动态数组,您可以采用相同的方式遍历其项:List<Salesman>
Salesman[]
public static void sortering(Salesman[] salesmenArray)
{
var level1 = new List<Salesman>();
var level2 = new List<Salesman>();
var level3 = new List<Salesman>();
var level4 = new List<Salesman>();
for (int i = 0; i < salesmenArray.Length; i++)
{
if (salesmenArray[i].level == 1)
{
level1.Add(salesmenArray[i]);
}
else if (salesmenArray[i].level == 2)
{
level2.Add(salesmenArray[i]);
}
else if (salesmenArray[i].level == 3)
{
level3.Add(salesmenArray[i]);
}
else if (salesmenArray[i].level == 4)
{
level4.Add(salesmenArray[i]);
}
}
if (level1Count > 0)
{
for (int i = 0; i < level1.Count; i++)
{
Console.WriteLine("Name: " + level1[i].name);
Console.WriteLine("District: " + level1[i].district);
Console.WriteLine("Items sold: " + level1[i].itemsSold);
}
Console.WriteLine("" + level1Count + " sellers have reached level 1");
}
//Same thing for level 2, 3 and 4
}
这里有一些其他的改进,然后你可以用你的代码来做。例如,如果 Salesman.level 可能只包含列表中的值,则可以将级别存储在 of 或数组中,并以更简单的方式添加项目。此外,字符串插值是一种更简单、更快、更易读的字符串连接语法。[1, 2, 3, 4]
List
List<Salesman>
List<Salesman>
// here we creates a new array of lists and initialize it with 4 empty lists of Salesman
var levels = new List<Salesman>[]
{
new List<Salesman>(),
new List<Salesman>(),
new List<Salesman>(),
new List<Salesman>()
};
foreach(var salesmen in salesmenArray)
{
// (salesmen.level - 1)-th list stores salesmen with that level
levels[salesmen.level - 1].Add(salesmen);
}
// you can iterate salesmen of all levels with nested loops
for(int level = 0; level < levels.Lenth; level++)
{
foreach(var salesman in levels[level])
{
Console.WriteLine($"Name: {salesman.name}");
Console.WriteLine($"District: {salesman.district}");
Console.WriteLine($"Items sold: {salesman.itemsSold}");
}
// Count property gets the number of elements contained in the List<T> so you don't need to decrement this value for display the number of salesmen with this level
Console.WriteLine($"{levels[level].Count} sellers have reached level {level + 1}");
}
最后,还有一种有趣的机制来操作 .NET 中的集合,称为 LINQ。可以使用 LINQ 语法来选择、筛选、分组和聚合数据。LINQ是可读的高效和强大的工具。下面是使用 LINQ 重写的代码示例:
foreach(var group in salesmenArray
.GroupBy(salesman => salesman.level)
.OrderBy(groups => groups.Key))
{
foreach(var salesman in group)
{
Console.WriteLine($"Name: {salesman.name}");
Console.WriteLine($"District: {salesman.district}");
Console.WriteLine($"Items sold: {salesman.itemsSold}");
}
Console.WriteLine($"{group.Count()} sellers have reached level {group.Key}");
}
评论
气泡在哪里排序?首先对数组进行排序,然后使用计数器遍历数组以计算每个级别并打印同一循环的输出。
// bubble sort
for (int i = 0; i < salesmenArray.Length; i++)
for (int j = 0; j < salesmenArray.Length - 1; j++)
if(salesmenArray[j].itemsSold > salesmenArray[j+1].itemsSold)
{
//swap positions
//...
}
int counter = 0;
int lastLevel = 1; //if 1 is the min level
for (int i = 0; i < salesmenArray.Length; i++)
{
if(salesmenArray[j].level != lastLevel)
{
//print summary
//...
counter = 0; //reset counter
}
// print detail lines
Console.WriteLine("Name: " + level1[i].name);
Console.WriteLine("District: " + level1[i].district);
Console.WriteLine("Items sold: " + level1[i].itemsSold);
counter++;
}
//print final summary for last level
//...
这。。。是供您填写的行。
评论
Vadim 的回答详细说明了代码失败的原因。他提出了一种通过s解决问题的方法。我也会走那条路。List
另一方面,你的方法很有效,但不是很有效,并且有一些陷阱(正如 Vadim 提到的,你正在创建 4 个级别数组,其大小与销售人员总数相同,然后你通过 将它们分配给每个级别,留下一些空白)。如果你想让你的方法工作,在打印循环中,在得到之前,检查不是。i
null
for
level1[i].name
level1[i]
null
如果您使用的是 IDE,我建议您在 for 循环中放置一个断点并查看 .level1
祝你好运!
评论