How to use Linq in C# to do this? - c#

I have this Object:
class Car
{
public int Id { get; set; }
public string Name { get; set; }
public Color Color { get; set; }
}
public enum Color
{
Red = 1,
Blue = 2,
Pink = 3,
Orange = 4,
}
How to create a linq query if I want take objects which have Red and Blue values:
query = query.Where(at => at.Color == Color.Red + Color.Blue);

If I take you at face value, and you want cars to be able to have more than one colour then you need to change your enum to use the Flags attribute.
Like this:
[Flags]
public enum Color
{
Red = 1,
Blue = 2,
Pink = 4,
Orange = 8,
}
Now I can write this code:
var cars = new []
{
new Car() { Name = "Red & Orange", Color = Color.Red | Color.Orange },
new Car() { Name = "Red & Blue", Color = Color.Red | Color.Blue },
};
var query = cars.Where(at => at.Color == (Color.Red | Color.Blue));
That, indeed, returns just the "Red & Blue" car.
However, if you meant or rather than and then you don't need to change your enum and the following is what you need:
query = query.Where(at => at.Color == Color.Red || at.Color == Color.Blue);

Either you can make the query with || or operator
query = query.Where(at => at.Color == Color.Red
|| at.Color == Color.Blue);
Or create an Color array to check whether the value is within the array.
query = query.Where(at => (new Color[] { Color.Red, Color.Blue }).Contains(at.Color));

Related

Joining Two list using LINQ Query and displaying only relevant data

I am new to programming and working on LINQ, I have two list both have different data, the thing I am trying to do is join both of them in a separate list and then display only "Black" and "White" car data using LINQ (Query or IQueryable whatever it is) here is my code, that do entirely different thing
static void Main(string[] args)
{
List<Cars> cars = new List<Cars>();
cars.Add (new Cars { Make = "Honda", Model = 2020, Color = "Black"});
cars.Add (new Cars { Make = "Suzuki", Model = 2020, Color = "White" });
cars.Add (new Cars { Make = "Toyota", Model = 2020, Color = "Green" });
cars.Add (new Cars { Make = "Kia", Model = 2020, Color = "Blue" });
List<MakeBy> makeby = new List<MakeBy>();
makeby.Add(new MakeBy { Color = "White", Country = "China" });
makeby.Add(new MakeBy { Color = "Black", Country = "Japan" });
makeby.Add(new MakeBy { Color = "White", Country = "Japan" });
makeby.Add(new MakeBy { Color = "White", Country = "Korea" });
var CombineCars = cars.Zip(makeby, (e, s) => e.Color + "White" + s.Color + "Black");
foreach(var item in CombineCars)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
See if the following works. If not, please specify more precisely, what output you need.
var CombineCars = cars.Join(maekby,
c => c.Color,
m => m.Color,
(c, m) => new
{
carMake = c.Make,
carModel = c.Model,
carColor = c.Color,
makeByColor = m.Color,
makeByCountry = m.Country
});
Now you can access it like:
foreach (var car in CombineCars)
{
Console.WriteLine($"Car model: {car.carModel}, car make: {car.carMake}"); //and so on
}
Haven't tested it, but it should do what you need.

LiveCharts ColumnSeries update Colours on Runtime

I am using LiveCharts 0.9.7 and 1.2.9 Geared Version on WPF to show population data on ColumnSeries.
Here is my scenario: At the beginning, I am filling Columns with Blue. I want to change the colour of a single Column's Value on runtime.
I tried to reach a single value with SeriesCollection[0].Values[0] but, there no Fill or Colour option, it is just Double.
I also tried to cast SeriesCollection[0] to ColumnSeries but, I couldn't achieve the result. Is it possible to update a single value's colour on runtime?
public SeriesCollection SeriesCollection { get; set; } = new SeriesCollection
{
new ColumnSeries
{
Title = "Population of Bodrum",
Values = new ChartValues<double> { 1500, 2500, 3700, 2000, 1000},
Fill = Brushes.Blue
}
};
You can specify a configuration by assigning a CartesianMapper to ColumnSeries.Configuration.
The following example changes the color of the third column of your given chart from blue to red:
public class ChartDataModel
{
public ChartDataModel()
{
this.BlueSeries = new ColumnSeries()
{
Title = "Population of Bodrum",
Values = new ChartValues<double> { 1500, 2500, 3700, 2000, 1000 },
Fill = Brushes.Blue
};
this.SeriesCollection = new SeriesCollection() { this.BlueSeries };
}
private void ChangeThirdChartPointColorToRed()
{
CartesianMapper<double> mapper = Mappers.Xy<double>()
.X((value, index) => index)
.Y(value => value)
.Fill((value, index) => index == 2 ? Brushes.Red : Brushes.Blue);
// Dynamically set the third chart point color to red
this.BlueSeries.Configuration = mapper;
}
// The actual chart data source
public SeriesCollection SeriesCollection { get; set; }
private ColumnSeries BlueSeries { get; set; }
}
You can also use the CartesianMapper to change the color of a point according to its y value by specifying a corresponding predicate. To draw all values that exceed a value of 2,000 red you could use the following mapper:
CartesianMapper<double> mapper = Mappers.Xy<double>()
.X((value, index) => index)
.Y(value => value)
.Fill((value, index) => value > 2000 ? Brushes.Red : Brushes.Blue);

Compare enum with integers

Please refer the below enums
public enum Fruit
{
Apple = 1,
Orange = 2,
Banana= 3
}
public enum Color
{
Orange = 1,
Yellow = 2,
Red= 3
}
Now I want to map Fruit with Color.So I implemented
public enum FruitColor
{
1= 3,
2= 1,
3= 2
}
I am getting an syntax error when I implement FruitColor
Identifier Expected
How to resolve this?
There is no point in using an enum to map enum values. I would use a dictionary:
Dictionary<Fruit, Color> FruitToColor = new Dictionary<Fruit, Color>
{ { Fruit.Apple, Color.Red }
, { Fruit.Orange, Color.Orange }
, { Fruit.Banana, Color.Yellow }
};
Color colorOfBanana = FruitToColor[Fruit.Banana]; // yields Color.Yellow
Also just putting it out there because I can, the only advantage is you can encode other data in a custom attribute. However, I'd go with the dictionary or a switch ;)
Given
public enum MyFruit
{
[MyFunky(MyColor.Orange)]
Apple = 1,
[MyFunky(MyColor.Yellow)]
Orange = 2,
[MyFunky(MyColor.Red)]
Banana = 3
}
public enum MyColor
{
Orange = 1,
Yellow = 2,
Red = 3
}
public static class MyExteions
{
public static MyColor GetColor(this MyFruit fruit)
{
var type = fruit.GetType();
var memInfo = type.GetMember(fruit.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof (MyFunkyAttribute), false);
if (attributes.Length > 0)
return ((MyFunkyAttribute)attributes[0]).Color;
throw new InvalidOperationException("blah");
}
}
public class MyFunkyAttribute : Attribute
{
public MyFunkyAttribute(MyColor color) { Color = color;}
public MyColor Color { get; protected set; }
}
Usage
var someFruit = MyFruit.Apple;
var itsColor = someFruit.GetColor();
Console.WriteLine("Fruit = " + someFruit + ", Color = " + itsColor);
Output
Fruit = Apple, Color = Orange
Full Demo Here
You can't have numbers as enum keys. You could use a dictionary to map the values:
var map = new Dictionary<Fruit, Color>
{
{ Fruit.Apple, Color.Red },
{ Fruit.Orange, Color.Orange },
{ Fruit.Banana, Color.Yellow }
};
To access the mapped values use:
var mappedValue = map[Fruit.Apple];
Alternatively, because you want to map the inverse value (1 to 3 and 3 to 1) you could use casts from an integer, although this could be dangerous because the result could be undefined.
var src = (int) Fruit.Apple; // src = 1;
var tar = 4 - src; // tar = 3;
var mapped = (Color) tar;
More generic example:
function Color Map(Fruit fruit)
{
var src = (int) fruit;
var tar = 4 - src;
var color = (Color) tar;
return color;
}
Member identifiers are not allowed to begin with numeric values, you can however use a method to get the proper values from each enum:
public Fruit GetFruit(this Color c) {
switch ((int)c) {
case 1: return (Fruit)3;
case 2: return (Fruit)2;
case 3: return (Fruit)1;
}
return 0;
}
The reverse of this method would give you the Color from the Fruit. You can call this method via the Color type as a static method:
Fruit myFruit = Color.GetFruit(Color.Orange);

Using HighCharts with Lambda Expression

I am experiencing trouble getting what I am looking for, in respect to setting series for highcharts. I want to use my table in my database to post the number for the y-axis.
So in my table I have the properties, ID, TeamName, TotalWins.
I only have 2 records
ID = 1, TeamName = Boston Red Sox, TotalWins? = 0 nullable because the MLB season hasn't started yet
ID = 2, TeamName = Baltimore Orioles, TotalWins? = 0
Here is my ActionResult for my Chart:
public ActionResult Chart()
{
Highcharts chart = new Highcharts("chart")
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Pie })
.SetTitle(new Title { Text = "Who Has more Wins?" })
.SetSubtitle(new Subtitle { Text = "Source: Sportscenter" })
.SetXAxis(new XAxis
{
Categories = new[] { "Boston Red Sox", "Baltimore Orioles" },
Title = new XAxisTitle { Text = "Teams" }
})
.SetYAxis(new YAxis
{
Min = 0,
Title = new YAxisTitle
{
Text = "Wins (Game)",
Align = AxisTitleAligns.High
}
})
.SetTooltip(new Tooltip { Formatter = "function() { return ''+ this.series.name +': '+ this.y +' millions'; }" })
.SetPlotOptions(new PlotOptions
{
Bar = new PlotOptionsBar
{
DataLabels = new PlotOptionsBarDataLabels { Enabled = true }
}
})
.SetLegend(new Legend
{
Layout = Layouts.Horizontal,
Align = HorizontalAligns.Right,
VerticalAlign = VerticalAligns.Top,
X = -100,
Y = 100,
Floating = true,
BorderWidth = 1,
BackgroundColor = new BackColorOrGradient(ColorTranslator.FromHtml("#FFFFFF")),
Shadow = true
})
.SetCredits(new Credits { Enabled = false })
.SetSeries(new[]
{
new Series { Data = new Data(new object[] { db.Teams.Where(x => x.TeamName == "Boston Red Sox").Count(x => x.TotalWins) /*where the issue is */ }) },
});
return View(chart);
}
cannot implicitly convert type 'int?' to 'bool'
How do I set this lambda expression so that it retrieves the total wins for the boston red sox and then again for the baltimore orioles?
The problem is here:
.Count(x => x.TotalWins)
Count either takes no arguments (in which case it returns the total count of the results of the preceding query), or a lambda that returns a boolean expression, in which case it returns a count of items that meet the criteria.
Do you mean .Sum(x => x.TotalWins)?

C# Linq Union On Attribute

I have two linq queries that I want to unionize on a common attribute:
One
{
Id,
Name,
Color
}
Two
{
Color,
Cost
}
I want to get the union of One and Two by unionizing on Color? If there is not a Two with a Color that corresponds to One, I want to set Cost to 0 in the output? How do I do this in LINQ?
Here is a sample using anonymous types on how to perform a left outer join:
var products = new[] {
new { Id = 1, Name = "Alpha", Color = "Red" },
new { Id = 2, Name = "Beta", Color = "Green" },
new { Id = 3, Name = "Gamma", Color = "Blue" }
};
var costs = new[] {
new { Color = "Red", Cost = 100 },
new { Color = "Blue", Cost = 200 },
new { Color = "Blue", Cost = 300 }
};
var query = products
.GroupJoin(
costs, p => p.Color, c => c.Color,
(p, c) => new { p.Id, p.Name, p.Color, Costs = c.DefaultIfEmpty() }
)
.SelectMany(
gj => gj.Costs,
(gj, c) => new { gj.Id, gj.Name, gj.Color, Cost = c == null ? 0 : c.Cost }
);
Query result:
Id Name Color Cost
-------------------
1 Alpha Red 100
2 Beta Green 0
3 Gamma Blue 200
3 Gamma Blue 300
This is called a join, not a union.
See the documentation.
You want a left outer join to keep the values appearing in the first list but are not present in the second.

Categories

Resources