1

My program has textboxes and a listView and info is typed into the textboxes and then displayed into the listview at the click of a button. the info is ID, first name, last name and yearly salary. The info is stored in array.

I want to find the person with the lowest salary. How do I go about doing this? (in C#)

this is my Form1:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Collections;


    namespace Employee_Program
    {
        public partial class Form1 : Form
        {


            public Form1()
            {
        em = new ArrayList();
        InitializeComponent();
    }

    public ArrayList em = new ArrayList();


    private void show_employee()
    {
        listView1.Items.Clear();
        foreach(Employee a in em)
        {
            int i = listView1.Items.Count;
            listView1.Items.Add(a.EmployeeId.ToString());
            listView1.Items[i].SubItems.Add(a.FirstName);
            listView1.Items[i].SubItems.Add(a.LastName);
            listView1.Items[i].SubItems.Add(a.YearSalary.ToString());


        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Employee a = new Employee();
        a.EmployeeId = float.Parse(employeeId.Text);
        a.FirstName = firstName.Text;
        a.LastName = lastName.Text;
        a.YearSalary = float.Parse(yearSalary.Text);
        em.Add(a);
        show_employee();


    }

    private void button2_Click(object sender, EventArgs e)
    {

    // this is the button that will return the lowest salary value. Preferably in a                        
    //message box? Any idea?

        }
    }}

this is my class, Employee:

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

       namespace Employee_Program
       {
class Employee
{
    protected float employeeId;
    protected string firstName;
    protected string lastName;
    protected float yearSalary;


    // first constructor
    public Employee()
    {
        employeeId = 0;
        firstName = "";
        lastName = "";
        yearSalary = 0;
    }

    // second constructor
    public Employee(float EmployeeId, string FirstName,
                           string LastName, float YearSalary) 
    {
        employeeId = EmployeeId;
        firstName = FirstName;
        lastName = LastName;
        yearSalary = YearSalary;
    }

    public float EmployeeId
    {
        get
        {
            return employeeId;
        }

        set
        {
            employeeId = value;
        }
    }

    public string FirstName
    {
        get
        {
            return firstName;
        }

        set
        {
            firstName = value;
        }
    }
    public string LastName
    {
        get
        {
            return lastName;
        }

        set
        {
            lastName = value;
        }
    }

    public float YearSalary
    {
        get
        {
            return yearSalary;
        }

        set
        {
            yearSalary = value;
        }
    }


           }

       }
user1336868
  • 109
  • 9

4 Answers4

2

Note: Be sure to include:

using System.Linq;

You can use a LINQ expression such as:

Employee[] employees;
//Populate employees   
var min = (from e in employees select e.YearSalary).Min();
Mike Christensen
  • 88,082
  • 50
  • 208
  • 326
2

MoreLINQ has a MinBy method. If you don't want to use MinBy, there are several ways to do it. I recommend this approach:

// Don't use an ArrayList, use a List<Employee>
Employee minEmp = employees.Aggregate(float.MinValue, (min, e) => (e.YearSalary < min.YearSalary) ? e : min);

If you need a list of all the employees with matching minimum salary, you could do something like this:

float min = employees.Min(e => e.YearSalary);
var minEmps = employees.Where(e => e.YearSalary == min);
Kendall Frey
  • 43,130
  • 20
  • 110
  • 148
  • this seems perfect but how do I get it to accept "employees"? do i declare that somewhere? – user1336868 Apr 17 '12 at 00:20
  • "Don't use an `ArrayList`, use a `List`". An `ArrayList` is untyped, which can lead to problems and code smell. And I used `employees` instead of `em`. I think it is more readable. – Kendall Frey Apr 17 '12 at 00:21
  • I've never used List before, so I have to redo the code in that? – user1336868 Apr 17 '12 at 00:31
  • I didn't see any place in your code where you would have to change anything, except for the variable declaration and in the constructor. Docs for `List<>`: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx BTW, why are you instantiating `em` twice? – Kendall Frey Apr 17 '12 at 00:42
  • I think it was a mistake, thank you! However, it does not like the use of "e" in "e =>" etc. Why is that? – user1336868 Apr 17 '12 at 00:47
  • Oh, that would be because you already have a local variable named e. you can replace e with emp, or anything, really. – Kendall Frey Apr 17 '12 at 00:57
  • hmm I tried that but then it suddenly doesn't like YearSalary :/ – user1336868 Apr 17 '12 at 00:59
  • Did you do this? `emp => emp.YearSalary == min` – Kendall Frey Apr 17 '12 at 01:01
  • yes I just did that and NOW it doesn't like the "employees" in "float min = employees.Min(emp => emp.YearSalary);". *facepalm* I'm so sorry but thank you for all this help BTW! – user1336868 Apr 17 '12 at 01:04
  • It doesn't like `employees`? What does it say? – Kendall Frey Apr 17 '12 at 01:08
1

Look into using a MinBy extension method. It's notably lacking in Linq. An implementation can be found here.

Then you'd simply:

Employee aCheapEmployee = employees.MinBy(e => e.Salary);

If you need to find all lowest paid employees:

var minSalary = employees.Min(e => e.Salary); 
IEnumerable<Employee> slaveLabourers = employees.Where(e => e.Salary==minSalary);
spender
  • 117,338
  • 33
  • 229
  • 351
1

Consider about refactoring your code.

  • you can use chain constructors to avoid initialization duplication
  • you can use auto-properties
  • its very strange that you use float as id. consider using something like int
  • usually camelCase used for parameters naming
  • consider using decimal type for salary

Your Employee class is much cleaner now:

public class Employee
{   
    public Employee()
        : this(0, "", "", 0)
    {
    }

    public Employee(int employeeId, string firstName,
                           string lastName, decimal yearSalary) 
    {
        EmployeeId = employeeId;
        FirstName = firstName;
        LastName = lastName;
        YearSalary = yearSalary;
    }

    public int EmployeeId  { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set;}
    public decimal YearSalary { get; set; }
}
  • consider using NumericUpDown control for numeric values input
  • consider using descriptive names for controls
  • consider adding new employee to the end of listView, instead of reloading all employees
  • consider using generic list for employees collection
  • usually PascalCase used for methods naming

Here is Form1 code:

private List<Employee> employees = new List<Employee>();

private void ShowEmployee(Employee employee)
{
    var item = employeeListView.Items.Add(employee.EmployeeId.ToString());
    item.SubItems.Add(employee.FirstName);
    item.SubItems.Add(employee.LastName);
    item.SubItems.Add(employee.YearSalary.ToString());
}

private void AddEmployeeButton_Click(object sender, EventArgs e)
{
    Employee employee = new Employee();
    employee.EmployeeId = (int)idNumericUpDown.Value;
    employee.FirstName = firstNameTextBox.Text;
    employee.LastName = lastNameTextBox.Text;
    employee.YearSalary = salaryNumericUpDown.Value;
    employees.Add(employee);
    ShowEmployee(employee);
}

private void LowestSalaryButton_Click(object sender, EventArgs e)
{
    decimal minSalary = employees.Min(em => em.YearSalary);
    MessageBox.Show(minSalary.ToString("C"), "Min salary");
} 
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • the only problem i'm having is this part: "Employee employee = new Employee(); employee.EmployeeId = (int)idNumericUpDown.Value; employee.FirstName = firstNameTextBox.Text; employee.LastName = lastNameTextBox.Text; employee.YearSalary = salaryNumericUpDown.Value; employees.Add(employee); ShowEmployee(employee);" it doesn't like the idNumericUpDown and the salaryNumericUpDown – user1336868 Apr 17 '12 at 01:10
  • @user1336868 thats two controls of type `NumericUpDown` which provide input for numeric values. You can still use TextBox, but you will have to handle incorrect input. – Sergey Berezovskiy Apr 17 '12 at 06:03
  • @user1336868 just replace `yearSalary` and `employeeId` textboxes. Drag two NumericUpDown controls from ToolBox to your form. And name them `idNumericUpDown` and `salaryNumericUpDown`. – Sergey Berezovskiy Apr 17 '12 at 12:56
  • ok I tried all of this but the program won't work. When I click the button nothing happens? – user1336868 Apr 17 '12 at 13:03
  • @user1336868 you need to assign `AddEmployeeButton_Click` to button1 Click event. `LowestSalaryButton_Click` to button2 Click event. Also consider to rename buttons to `addEmployeeButton` and `lowestSalaryButton`. – Sergey Berezovskiy Apr 17 '12 at 13:29
  • tHANK YOU SO MUCH. I am completely new to this and your answer was SO helpful. Thank you again. – user1336868 Apr 17 '12 at 13:58
  • Just wondering, if I wanted the persons full details to come up with the lowest salary how would I go about doing that? – user1336868 Apr 17 '12 at 14:00
  • E.g. `IEnumerable poors = employees.Where(em => em.YearSalary == minSalary);` keep in mind that there could be several employees with same min salary. – Sergey Berezovskiy Apr 17 '12 at 14:06
  • @user1336868 right after you got minSalary value. This statement will return list of employees which have same salary – Sergey Berezovskiy Apr 17 '12 at 14:32
  • so `decimal minSalary = employees.Min(em => em.YearSalary); IEnumerable poors = employees.Where(em => em.YearSalary == minSalary); MessageBox.Show(minSalary.ToString("C"), "Min salary");` ? – user1336868 Apr 17 '12 at 14:41
  • Exactly. When you get list of poor employees, you can do show their details. E.g. `poors.Count()` returns count of employees with min salary. `foreach(var poor in poors) MessageBox.Show(poor.FirstName + poor.LastName)` will show messageboxes with names of all poor people – Sergey Berezovskiy Apr 17 '12 at 14:52
  • so I can't get them all in one messagebox? – user1336868 Apr 17 '12 at 15:12
  • You can show another form with listBox and show poor employees there. Or you can build some string and show that string in MessageBox. Sorry, need to go now – Sergey Berezovskiy Apr 17 '12 at 15:31