Pxaml
Pxaml

Reputation: 555

Linq - How to refactor a multiline output using the same list

I would like to know what's a better way to improve this Linq set of code. Using xamarin forms and data binding. I need to pass individual fields to different labels and they all come from the same main list. I need to select those individuals items to pass them to each of the respective binding fields since each is expecting an only string.

var nameloc = MainList.Select(d => string.IsNullOrEmpty(d.name) ? "Not Available":d.name).FirstOrDefault();
var descrip = MainList.Select(d => string.IsNullOrEmpty(d.descr) ? "Not Available":d.descr).FirstOrDefault();
var cap = MainList.Select(d => string.IsNullOrEmpty(d.cap) ? "Not Available":d.cap).FirstOrDefault();
var ruls= MainList.Select(d => string.IsNullOrEmpty(d.ruls) ? "Not Available":d.ruls).FirstOrDefault();
var name = MainList.Select(d => string.IsNullOrEmpty(d.nameAddress) ? "Not Available":d.nameAddress).FirstOrDefault();
var email = MainList.Select(d => string.IsNullOrEmpty(d.EmailAddress) ? "Not Available":d.EmailAddress).FirstOrDefault();
var phone = MainList.Select(d => string.IsNullOrEmpty(d.phone) ? "Not Available":d.phone).FirstOrDefault();
LC = nameloc;
Description = descrip;
Cat = cap;
Rules = ruls;
Name = name;
Phone = phone;
email = email;

Upvotes: 0

Views: 82

Answers (4)

brainless coder
brainless coder

Reputation: 6430

I think the minimalist approach would be using a lambda expression as parameter to get your values. So something like this might work -

//assumed class for demonstration only
public class Data
{
    public string name { get; set; }
    public string desc { get; set; }
}

//extension method 
public static class ListExtensions
{
    public static string GetFirstProperty(this List<Data> list, Expression<Func<Data, string>> predicate)
    {
        //you can ignore the compilation here, if you use Func<Data,string> instead of Expression<Func<Data,string>>
        var compiledSelector = predicate.Compile();
        return list.Select(x => string.IsNullOrWhiteSpace(compiledSelector(x)) ? "Not Available" : compiledSelector(x)).FirstOrDefault();
    }
}

var name = MainList.GetFirstProperty(x => x.name);
var desc = MainList.GetFirstProperty(x => x.desc);

I assumed the data class. Use your own class as needed.

Upvotes: 1

Jonas H&#248;gh
Jonas H&#248;gh

Reputation: 10874

It makes no sense to use Linq in this way. The only collection-oriented operation in your code is the call to .FirstOrDefault(). Simply do that, and then add a helper method for getting the fallback string if the input is null or empty, e.g.:

public static string GetPropertyWithFallback(Item item, Func<Item, string> getter) {
  if (item != null) {
    var val = getter(item);
    if (!string.IsNullOrEmpty(val)) {
      return val;
    }
  }
  return "Not available";
}


public static void Main() {
  var mainList = new List<Item>();

  var firstItem = mainList.FirstOrDefault();
  var name = GetPropertyWithFallback(firstItem, i => i.Name);
  var descr = GetPropertyWithFallback(firstItem, i => i.Descr); 
  //etc.
}

Upvotes: 1

Marco Salerno
Marco Salerno

Reputation: 5201

I suggest you this approach:

var item = MainList.Select(x => 
    new { 
        name = string.IsNullOrEmpty(x.name) ? "Not Available" : x.name,
        //Same for other properties
    }
).FirstOrDefault();
LC = item.name;
//Same for other properties

Upvotes: 1

canton7
canton7

Reputation: 42320

Note that your code has the perhaps slightly odd behaviour that if MainList is empty, each of the final strings are all null.

If this is intentional, you can add a helper function like this:

string ValueOrNotAvalable(MainListItem item, string value)
{
    if (item == null)
        return null;
    return string.IsNullOrEmpty(value) ? "Not Available" : value;
}

var firstItem = MainList.FirstOrDefault();

LC = ValueOrNotAvalable(firstItem, firstItem?.name);
Description = ValueOrNotAvailable(firstItem, firstItem?.descr);
...

If you actually wanted to use the string "Not Available" if MainList is empty, you can simplify it a bit:

string ValueOrNotAvailable(string value) => string.IsNullOrEmpty(value) ? "Not Available" : value;

var firstItem = MainList.FirstOrDefault();

LC = ValueOrNotAvalable(firstItem?.name);
Description = ValueOrNotAvailable(firstItem?.descr);
...

Upvotes: 2

Related Questions