Get values of an enum variable having duplicate values with different keys - c#

I've an Enum for 52 playing cards, as mentioned below,
public enum Card
{
AceClubs = 11,
AceDiamonds = 11,
AceHearts = 11,
AceSpades = 11,
DeuceClubs = 2,
DeuceDiamonds = 2,
DeuceHearts = 2,
DeuceSpades = 2,
EightClubs = 8,
EightDiamonds = 8,
EightHearts = 8,
EightSpades = 8,
FiveClubs = 5,
FiveDiamonds = 5,
FiveHearts = 5,
FiveSpades = 5,
FourClubs = 4,
FourDiamonds = 4,
FourHearts = 4,
FourSpades = 4,
JackClubs = 11,
JackDiamonds = 11,
JackHearts = 11,
JackSpades = 11,
KingClubs = 13,
KingDiamonds = 13,
KingHearts = 13,
KingSpades = 13,
NineClubs = 9,
NineDiamonds = 9,
NineHearts = 9,
NineSpades = 9,
QueenClubs = 12,
QueenDiamonds = 12,
QueenHearts = 12,
QueenSpades = 12,
SevenClubs = 7,
SevenDiamonds = 7,
SevenHearts = 7,
SevenSpades = 7,
SixClubs = 6,
SixDiamonds = 6,
SixHearts = 6,
SixSpades = 6,
TenClubs = 10,
TenDiamonds = 10,
TenHearts = 10,
TenSpades = 10,
ThreeClubs = 3,
ThreeDiamonds = 3,
ThreeHearts = 3,
ThreeSpades = 3
}
I want to create a list from enum
var cards = Enum.GetValues(typeof(Card));
but it returns duplicate keys in list.

use Enum.GetNames instead of Enum.GetValues

I suggested using two enums for suit and value:
public enum CardSuit {
Clubs = 1,
Diamonds = 2,
Hearts = 3,
Spades = 4,
};
public enum CardValue {
Ace = 1,
Deuce = 2,
...
King = 13,
};
then implement an extension method to get actual card value (since both Jack and Ace corresponds to 11):
public static class ValueExtensions() {
public static int ActualValue(this CardValue value) {
if (value == CardValue.Ace)
return 11; // Ace is 11
else
return (int) value;
}
}
Finally
public class Card {
public Card (CardSuit suit, CardValue value) {
Suit = suit;
Value = value;
}
public CardSuit Suit {get; private set;}
public CardValue Value {get; private set;}
}
...
Card[] pack = Enum
.GetValues(typeof(CardSuit))
.OfType<CardSuit>()
.SelectMany(suit => Enum
.GetValues(typeof(CardValue))
.OfType<CardValue>()
.Select(value => new Card(suit, value)))
.ToArray();
//TODO: Shuffle the pack here
Card[] hand = pack.Take(5).ToArray();
int handValue = hand.Sum(card => card.Value.ActualValue());

Your mistake is to use the same value for different things. Enums are not intended to have duplicate values (unless they mean the same thing).
When the program is running, enums are held as integers - not names.
The debugger then takes an integer from the program (4) and displays it as the first enum it can find (FourClubs). This is just for your convenience when debugging - the program still uses the integer (4).

You can remove the duplicates from the array using Linq:
var uniqueCards = cards.Distinct().ToArray();

Related

Enum.HasFlag is not working as expected [duplicate]

This question already has answers here:
HasFlag always returns True
(5 answers)
Closed 4 years ago.
I have a Enum with Flags like this:
[Flags]
public enum ItemType
{
Shop,
Farm,
Weapon,
Process,
Sale
}
Then I have several objects in a list with some flags set and some flags not set. It looks like this:
public static List<ItemInfo> AllItems = new List<ItemInfo>
{
new ItemInfo{ID = 1, ItemType = ItemType.Shop, Name = "Wasserflasche", usable = true, Thirst = 50, Hunger = 0, Weight = 0.50m, SalesPrice = 2.50m, PurchasePrice = 5, ItemUseAnimation = new Animation("Trinken", "amb#world_human_drinking#coffee#female#idle_a", "idle_a", (AnimationFlags.OnlyAnimateUpperBody | AnimationFlags.AllowPlayerControl)) },
new ItemInfo{ID = 2, ItemType = ItemType.Sale, Name = "Sandwich", usable = true, Thirst = 0, Hunger = 50, Weight = 0.5m, PurchasePrice = 10, SalesPrice = 5, ItemUseAnimation = new Animation("Essen", "mp_player_inteat#pnq", "intro", 0) },
new ItemInfo{ID = 3, ItemType = (ItemType.Shop|ItemType.Process), Name = "Apfel", FarmType = FarmTypes.Apfel, usable = true, Thirst = 25, Hunger = 25, Weight = 0.5m, PurchasePrice = 5, SalesPrice = 2, ItemFarmAnimation = new Animation("Apfel", "amb#prop_human_movie_bulb#base","base", AnimationFlags.Loop)},
new ItemInfo{ID = 4, ItemType = ItemType.Process, Name = "Brötchen", usable = true, Thirst = -10, Hunger = 40, Weight = 0.5m, PurchasePrice = 7.50m, SalesPrice = 4}
}
Then I go trough the list with a loop and ask if the flag ItemType.Shop is set or not, like this:
List<ItemInfo> allShopItems = ItemInfo.AllItems.ToList();
foreach(ItemInfo i in allShopItems)
{
if (i.ItemType.HasFlag(ItemType.Shop))
{
API.consoleOutput(i.Name);
}
}
This is the output of my loop - it shows all items in the list, and the .HasFlag method always returns true in this case.
Wasserflasche
Sandwich
Apfel
Brötchen
Try to assign values to your enum
[Flags]
public enum ItemType
{
Shop = 1,
Farm = 2,
Weapon = 4,
Process = 8,
Sale = 16
}
Here are some Guidelines for FlagsAttribute and Enum (excerpt from Microsoft Docs)
Use the FlagsAttribute custom attribute for an enumeration only if a bitwise operation (AND, OR, EXCLUSIVE OR) is to be performed on a numeric value.
Define enumeration constants in powers of two, that is, 1, 2, 4, 8, and so on. This means the individual flags in combined enumeration constants do not overlap.
You should assign values to your enums. All the flags attribute does is change how the ToString method works. I would use a bitwise operator to make it less likely to make a mistake:
[Flags]
public enum ItemType
{
Shop = 1 << 0, // == 1
Farm = 1 << 1, // == 2
Weapon = 1 << 2, // == 4
Process = 1 << 3, // == 8
Sale = 1 << 4 // == 16
}

Sort ObservableCollection in Combobox C# WPf

I want to set sorted the ObservableCollection in combobox,
my result without sorted:
my ViewModel:
private ObservableCollection<IdentificationSystemType> codeTypeEnum;
public IdentificationSystemType CodeType
{
get { return codeType; }
set { codeType = value;
OnPropertyChanged("CodeType");
}
}
public NewIdentificationSystemViewModel()
{
_identificationToAdd = new IdentificationSystem();
identificationDeviceToAdd = new IdentificationDevice();
_resetIdentificationCmd = new RelayCommand<string>(resetIdentification);
saveCommand = new RelayCommand<string>(addFunc, canSave);
codeTypeEnum = new ObservableCollection<IdentificationSystemType>(Enum.GetValues(typeof(IdentificationSystemType)).Cast<IdentificationSystemType>());
}
I had try with var ordered = codeTypeEnum.OrderBy(x => x); but nothing ..it is the same
my Enum declaration:
public enum IdentificationTypes : int
{
TerminalEntryGate = 1,
TerminalExitGate = 2,
LoadingAreaEntryGate = 3,
LoadingAreaExitGate = 4,
IslandEntryGate = 5,
IslandExitGate = 6,
BayEntryGate = 7,
BayExitGate = 8,
ScalingAreaEntryGate = 9,
ScalingAreaExitGate = 10,
OfficeAreaEntryGate = 11,
OfficeAreaExitGate = 12,
TankFarmEntryGate = 13,
TankFarmExitGate = 14,
StagingAreaEntryGate = 15,
StagingAreaExitGate = 16,
LoadingBayIdentification = 21,
LoadingArmIdentification = 22,
LoadingIslandIdentification = 23,
PresetIdentification = 27
}
How can I fix that?
thanks,
Change:
codeTypeEnum = new ObservableCollection<IdentificationSystemType>(Enum.GetValues(typeof(IdentificationSystemType))
.Cast<IdentificationSystemType>());
to:
codeTypeEnum = new ObservableCollection<IdentificationSystemType>(Enum.GetValues(typeof(IdentificationSystemType))
.Cast<IdentificationSystemType>().OrderBy(x => x.ToString()));
to force it to be ordered alphabetically.
As your enum is of type int you are ordering your collection by those numbers. If you want to order your collection alphabetically you need to parse the integers to strings first.
You can do this in the key selector function you are giving the OrderBy method.
var values = Enum.GetValues(typeof(IdentificationTypes)).Cast<IdentificationTypes>();
var valueList = new ObservableCollection<IdentificationTypes>(values);
var orderedList = valueList.OrderBy(x => x.ToString());

Hi, I'm trying to make a percentage calculator. I have an array and I want to see the number of times each element occurs

I'm trying to make a percentage calculator. I have an array and I want to see the number of times each element occurs and then divide it by the total number of occurrences to get a percentage. So I want an output like:
*/ 1 = 12%
*/ 2 = 15%
...
int[] n1 = { 1, 2, 3, 4, 5, 6, 1, 2, 4, 5, 6, 3, 1, 2, 5, 6 };
int c = n1.Count();
Console.WriteLine ("the total number of " + c );
Dictionary<int, int> counts = n1.GroupBy (x => x).ToDictionary (g => g.Key, g => g.Count ());
Try something like this:
int[] n1 = { 1, 2, 3, 4, 5, 6, 1, 2, 4, 5, 6, 3, 1, 2, 5, 6 };
int c = n1.Count();
var keyValue = n1.GroupBy (n => n).Select (n=> new KeyValuePair<int,string>(n.Key,((decimal)n.Count()/(decimal)c).ToString("0.0%")));
Response:
Key = 1, Value = 18.8%
Key = 2, Value = 18.8%
Key = 3, Value = 12.5%
Key = 4, Value = 12.5%
Key = 5, Value = 18.8%
Key = 6, Value = 18.8%

Change array according to the sequence

I have some Image sliders, and I wanted to change the sequence of the image slider. Current sequence is set from a database field (fetch the set of sequence numbers from the database and show it).
Now, I want to change the sequence number.Lets say,
My slider sequence is 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 & I need to change the 4th position slider to 8th position and after that my slider number sequence is 1, 2, 3, 5, 6, 7, 4, 8, 9, 10.
Here is an image to make it easy to understand
I have a int array with current sequence,
int[] currentSequence = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
MyCode:
int[] currentSequence = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var currentPosition = iproductrepositroy.GetSingle(x => x.ProductName.Equals(ProductName)).ProductSequence;// 4th position
var expectedPosition = ChangeSequence;// 8th position
if (currentPosition < expectedPosition)//right shift -->
{
int i = 0;
for (i = (int)currentPosition + 1; i < expectedPosition; i++)
{
// I wanted to know how to change the above array here
}
}
else//left shift <--
{
int i;
for (i = (int)currentPosition - 1; i > expectedPosition; i--)
{
}
}
This might be easier for you to do in a List:
class Program
{
static void Main(string[] args)
{
int currentPosition = 3;
int expectedPosition = 7;
int adjust = (currentPosition < expectedPosition) ? 1 : 0;
List<int> list = new List<int> { 1,2,3,4,5,6,7,8,9,10};
var item = list[currentPosition];
list.RemoveAt(currentPosition);
list.Insert(expectedPosition - adjust , item); //Insert position may be one less at the moment, so use calculated adjustment
foreach (int i in list)
{
Console.WriteLine(i.ToString());
}
var discard = Console.ReadKey();
}
}
Unless I've misunderstood your requirements then this is the simplest way to do the reordering:
var currentSequence = new [] { 1,2,3,4,5,6,7,8,9,10 };
var reordering = new [] { 1,2,3,5,6,7,4,8,9,10 };
var reorderedSequence =
reordering
.Select(r => currentSequence[r - 1])
.ToArray();
To show that this works, try it with this:
var currentSequence = new [] { "A","B","C","D","E","F","G","H","I","J" };
That gives back:
{ "A", "B", "C", "E", "F", "G", "D", "H", "I", "J" }

How to merge 2 List<T> and removing duplicate values from it in C#

I have two lists List that I need to combine in third list and remove duplicate values from that lists
A bit hard to explain, so let me show an example of what the code looks like and what I want as a result, in sample I use int type not ResultAnalysisFileSql class.
first_list = [1, 12, 12, 5]
second_list = [12, 5, 7, 9, 1]
The result of combining the two lists should result in this list:
resulting_list = [1, 12, 5, 7, 9]
You'll notice that the result has the first list, including its two "12" values, and in second_list has an additional 12, 1 and 5 value.
ResultAnalysisFileSql class
[Serializable]
public partial class ResultAnalysisFileSql
{
public string FileSql { get; set; }
public string PathFileSql { get; set; }
public List<ErrorAnalysisSql> Errors { get; set; }
public List<WarningAnalysisSql> Warnings{ get; set; }
public ResultAnalysisFileSql()
{
}
public ResultAnalysisFileSql(string fileSql)
{
if (string.IsNullOrEmpty(fileSql)
|| fileSql.Trim().Length == 0)
{
throw new ArgumentNullException("fileSql", "fileSql is null");
}
if (!fileSql.EndsWith(Utility.ExtensionFicherosErrorYWarning))
{
throw new ArgumentOutOfRangeException("fileSql", "Ruta de fichero Sql no tiene extensión " + Utility.ExtensionFicherosErrorYWarning);
}
PathFileSql = fileSql;
FileSql = ObtenerNombreFicheroSql(fileSql);
Errors = new List<ErrorAnalysisSql>();
Warnings= new List<WarningAnalysisSql>();
}
private string ObtenerNombreFicheroSql(string fileSql)
{
var f = Path.GetFileName(fileSql);
return f.Substring(0, f.IndexOf(Utility.ExtensionFicherosErrorYWarning));
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (!(obj is ResultAnalysisFileSql))
return false;
var t = obj as ResultAnalysisFileSql;
return t.FileSql== this.FileSql
&& t.PathFileSql == this.PathFileSql
&& t.Errors.Count == this.Errors.Count
&& t.Warnings.Count == this.Warnings.Count;
}
}
Any sample code for combine and removing duplicates ?
Have you had a look at Enumerable.Union
This method excludes duplicates from the return set. This is different
behavior to the Concat
method, which returns all the elements
in the input sequences including
duplicates.
List<int> list1 = new List<int> { 1, 12, 12, 5};
List<int> list2 = new List<int> { 12, 5, 7, 9, 1 };
List<int> ulist = list1.Union(list2).ToList();
// ulist output : 1, 12, 5, 7, 9
why not simply eg
var newList = list1.Union(list2)/*.Distinct()*//*.ToList()*/;
oh ... according to the documentation you can leave out the .Distinct()
This method excludes duplicates from
the return set
Union has not good performance : this article describe about compare them with together
var dict = list2.ToDictionary(p => p.Number);
foreach (var person in list1)
{
dict[person.Number] = person;
}
var merged = dict.Values.ToList();
Lists and LINQ merge: 4820ms
Dictionary merge: 16ms
HashSet and IEqualityComparer: 20ms
LINQ Union and IEqualityComparer: 24ms
Use Linq's Union:
using System.Linq;
var l1 = new List<int>() { 1,2,3,4,5 };
var l2 = new List<int>() { 3,5,6,7,8 };
var l3 = l1.Union(l2).ToList();
List<int> first_list = new List<int>() {
1,
12,
12,
5
};
List<int> second_list = new List<int>() {
12,
5,
7,
9,
1
};
var result = first_list.Union(second_list);

Categories