Reputation: 376
So I have an object of Hotels and a single payment could contain payment for multiple hotel bookings. So I ultimately retrieve a list of Payments and some of those in the list will only differ in the Payment booking but the same HotelID. So I would in that case just add to the Hotel's attribute List reservationNumber.
Now I am making something along the lines of this where I am using flags to know whether this entry is going to be the same as the previous if it is then added to the reservationNumber list if not, and it is a first time with an object make a copy of it.
Public Struct Hotel
{
...
List<string> ReservationNumbers {get; set;}
}
bool firstLoop = true;
foreach (var payment in Payments)
{
if (firstLoop)
{
pItem.CompanyID = payment.CompanyID;
firstLoop = false;
}
if(eHotel.HotelID == payment.HotelID)
{
eHotel.InvoiceNumbers.Add(payment.reservationNumber);
finalLoopWithHotel = false;
firstLoopWithHotel = false;
}
else if (!firstLoopWithHotel)
{
firstLoopWithHotel = true;
eHotel.HotelName = payment.HotelName;
eHotel.HotelAddress1 = payment.HotelAddress1;
eHotel.HotelAddress2 = payment.HotelAddress2;
eHotel.HotelAddress3 = payment.HotelAddress3;
eHotel.HotelCity = payment.HCity;
eHotel.HotelPostalCode = payment.HZip;
eHotel.ReservationNumbers.Add(payment.reservationNumber);
}
else
{
finalLoopWithHotel = true;
previousHotel = eHotel;
eHotel.HotelName = payment.HotelName;
eHotel.HotelAddress1 = payment.HotelAddress1;
eHotel.HotelAddress2 = payment.HotelAddress2;
eHotel.HotelAddress3 = payment.HotelAddress3;
eHotel.HotelCity = payment.HCity;
eHotel.HotelPostalCode = payment.HZip;
eHotel.ReservationNumbers.Add(payment.reservationNumber);
}
if (firstLoopWithHotel && finalLoopWithHotel)
{
firstLoopWithHotel = false;
finalLoopWithHotel = false;
pItem.HotelList.Add(previousHotel);
}
}
Upvotes: 0
Views: 318
Reputation: 4528
If you're looping through a list and you need to find the previous or next item, then you could use a for loop. This allows you to loop through each row using the indexes. You can examine other rows by adding to the index (e.g minus or add 1 to retrieve the previous & next items).
For example:
for (int i = 0; i < payments.Count; i++)
{
var currentPayments = payments[i];
// (Nullable<Payment>) is used because Payment is a struct. Can be removed if you use a class.
var previousPayments = i == 0 ? (Nullable<Payment>)null : payments[i-1];
var nextPayments = i == payments.Count-1 ? (Nullable<Payment>)null : payments[i+1];
}
It looks like the requirements are to; retrieve a list of hotels and combine the reservation numbers. The most efficient way to achieve this (and more readable) is through Linq. Use the group() function to combine all the hotels (by hotelId). This returns a group collection. Then assign the hotel details using first() (to get the first item in the group). ReservationNumbers can then be combined into one list (per hotel) using SelectMany(). Optionally you can call Distinct() to remove duplicate ReservationNumbers.
For example, you can replace foreach statement with:
List<Hotel> hotels = payments // Note: Hotel might not be the correct name / terminology.
.GroupBy(m => m.HotelID)
.Select(n => new Hotel()
{
HotelID = n.First().HotelID,
HotelName = n.First().HotelName,
// TODO: Add the First() item for all properties.
// Get a list of all reservationNumber for the hotel using SelectMany(). Remove duplicates with Distinct() (although there shouldn't be any)
ReservationNumbers = n.Select(o => o.reservationNumber).Distinct().ToList()
}).ToList();
If you want to improve the code a bit more, I would suggest changing your model to use classes instead of structs and also grouping the hotel details into it's own class.
For example:
public class Hotel
{
public int ID { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
public class Reservations
{
public Hotel Hotel { get; set; }
public List<string> ReservationNumbers { get; set; }
}
List<Reservations> hotelReservations = reservations // original would have been "payments"
.GroupBy(m => m.Hotel.ID)
.Select(n => new Reservations()
{
Hotel = n.First().Hotel, // All the hotels details get copied across as a new object (in 1 call).
ReservationNumbers = n.SelectMany(o => o.ReservationNumbers).Distinct().ToList()
}).ToList();
Upvotes: 1