How to calculate the turns of the players based on their dexterity? - c#

public void CalcolaTurni()
{
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("1", DestrezzaGiocatore1);
dict.Add("2", DestrezzaGiocatore2);
foreach (var item in dict.OrderByDescending(r => r.Value))
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
array.Add(item.value)
}
}
This is what I have done so far. I'm using a dictionary to store the name of the player and its dexterity and an array to store each dexterity value to sort it.
Okay let's say I have three players and their respective speed. I'd like to store each name as a key and each value as their speed (int) in a dictionary. Then I'd like to somehow find which one of them has the highest speed value and return its name. For example: Carl:10 Mark:12 John:11 -> Mark

Encapsulate the player and their properties together in a class rather than keeping them together with a dictionary, it'll make it easier to work with.
For example, create a class to model player stats:
public class PlayerStats
{
public string PlayerId { get; set; }
public int Dexterity { get; set; }
}
Then you can use it like this:
public static void Main()
{
var DestrezzaGiocatore1 = 5;
var DestrezzaGiocatore2 = 1;
var DestrezzaGiocatore3 = 6;
List<PlayerStats> playerStats = new List<PlayerStats>()
{
new PlayerStats() { PlayerId = "1", Dexterity = DestrezzaGiocatore1 },
new PlayerStats() { PlayerId = "2", Dexterity = DestrezzaGiocatore2 },
new PlayerStats() { PlayerId = "3", Dexterity = DestrezzaGiocatore3 }
};
var statsSorted = playerStats.OrderByDescending(a => a.Dexterity);
Console.WriteLine($"Player {statsSorted.First()} has the highest dexterity: {statsSorted.First().Dexterity}");
foreach (var playerStat in statsSorted)
{
Console.WriteLine($"Player {playerStat.PlayerId}: {playerStat.Dexterity}");
}
Console.ReadKey();
}

Related

Multi-Type and Multi-Dimensional Array (or List or Dictionary)?

Couldnt find exact question... I want to create a list(or dictionary or array, whatever it is called in C#, .NET), where i can store different types of arrays/lists/dicts.
for example, in PHP, i do in this way:
$x= array (
'Names'=> array( "James", "Nicolas", "Susan"), //Strings
'Age'=> array( 18, 52, 37), //Int
'Male'=> array( true, true, false), //Bool
);
How to achieve similar in C# / .NET ?
p.s. or if possible, Multi-Multi types, like:
$y = array (
$x => (
..... multi-element, like above
),
$z => (
..... multi-element, like above
)
);
In pre-version 7, C#, you have to create a class that can store your lists:
class Item {
public List<string> Names { get; }
public List<int> Ages { get; }
public List<bool> Males { get; }
}
You can also use a tuple, with the disadavantage of not having descriptive property names:
Tuple<List<string>, List<int>, List<bool>> tuple =
Tuple.Create(new List<string>(), new List<int>(), new List<bool>());
In C# 7 you can use value tuples without having to create a class:
(List<string> Names, List<int> Ages, List<bool> Males) itemLists =
(new List<string>(), new List<int>(), new List<bool>());
And access the components like this:
List<string> names = itemLists.Names;
You should though seriously consider to not create a class that contains lists, but a list that contains classes (or tuples). Here is an example with C# 7 value tuples:
List<(string Name, int Age, bool Male)> list = new List<(string, int, bool)>();
This construct is usually easier to handle, because you can loop one list and then handle one item that contains all related data.
Create a class that holds the information as List<string>, List<int> and List<string>. However a much better approach is to hold all the information for a single entity was a single class and store a list of those items:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public bool Male { get; set; }
}
Now store instances of that type in a list:
var list = new List<Person> {
new Person { Name = "James", Age = 18, Male = true },
new Person { Name = "Nicolas", Age = 52, Male = true },
new Person { Name = "Susan", Age = 37, Male = false }
};
This way you don´t need to "synchronize" all three lists, you have only one list instead.
If you really must use the approach you described define a class holding three different lists:
class Persons
{
public List<string> Names { get; set; }
public List<int> Ages { get; set; }
public List<bool> Male { get; set; }
}
Now you can create your persons as follows:
var persons = new Persons {
Names = new List<string> { "James", "Nicolas", "Susan"},
Ages = new List<int> { 17, 53, 37 },
Male = new List<bool> { true, true, false }
}
However this is quite difficult as every time you delete a name for example you´d also have to delete the appropriate age- and male-element also. Something like this:
persons.Names.RemoveAt(1);
persons.Ages.RemoveAt(1);
persons.Male.RemoveAt(1);
As #HimBromBeere said you may create a Person class:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public bool Male { get; set; }
}
Now you need to define another class that would store a result
public class Result
{
public List<string> Names { get; } = new List<string>();
public List<int> Age { get; } = new List<int>();
public List<bool> Male { get; } = new List<bool>();
}
At this time you can convert list of persons to your expected output with Linq
var persons = new List<Person> {
new Person { Name = "James", Age = 18, Male = true },
new Person { Name = "Nicolas", Age = 52, Male = true },
new Person { Name = "Susan", Age = 37, Male = false }
};
var result = persons.Aggregate(new Result(), (c, n) =>
{
c.Names.Add(n.Name);
c.Age.Add(n.Age);
c.Male.Add(n.Male);
return c;
});
If you are using C# 3 or higher you can use anonymous objects:
var x = new
{
Names = new[] {"James", "Nicolas", "Susan"},
Age = new[] {18, 52, 37},
Male = new[] {true, true, false}
};
for your second example you may use this code:
var y = new
{
x = new
{
Names = new[] {"James", "Nicolas", "Susan"},
Age = new[] {18, 52, 37},
Male = new[] {true, true, false}
},
// z = new { /* same code as above */ }
};

Excluding items from a list that exist in another list

I have a list for example List<string> ListProviderKeys that has some values in it.
I also have a second list from a class below, for example List<ChangesSummary> SecondList;
public class ChangesSummary
{
public string TableName { get; set; }
public string ProviderKey { get; set; }
public string ProviderAdrsKey { get; set; }
public string ProviderSpecialtyKey { get; set; }
public string FieldName{ get; set; }
}
Imagine the values that first list holds is the same kind of values we put in ProviderKey field in the second list.
Now What I want is to trim down the second list to only have values that their ProviderKey IS NOT already in the first list.
How Can I do that? I know the operator Except but not sure how to apply it in this situation!
The best I can think of is :
A) Create dictionary and use its fast lookups
B) Use LINQ .Where method with .ContainsKey() on this dictionary which internally uses Hashtable and performs quick lookups.
This should reduce search complexity to almost O(1) rather than O(N) ro worse (when we use LINQ .Where() with .Any() or .Contains() and that leads to nested loops).
From MSDN page :
The Dictionary generic class provides a mapping from a set of keys to
a set of values. Each addition to the dictionary consists of a value
and its associated key. Retrieving a value by using its key is very
fast, close to O(1), because the Dictionary class is implemented as a
hash table.
So what we can do is :
Dictionary<string, string> dict = ListProviderKeys.ToDictionary(s => s);
var newList = SecondList.Where(e => !dict.ContainsKey(e.ProviderKey)).ToList();
Here is a very simple, short, but complete example illustrating it and also testing its performance :
class Person
{
public int Id { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<int> ints = new List<int>();
List<Person> People = new List<Person>(1000);
for (int i = 0; i < 7500; i++)
{
ints.Add(i);
ints.Add(15000 - i - 1);
}
for (int i = 0; i < 45000; i++)
People.Add(new Person() { Id = i });
Stopwatch s = new Stopwatch();
s.Start();
// code A (feel free to uncomment it)
//Dictionary<int, int> dict = ints.ToDictionary(p => p);
//List<Person> newList = People.Where(p => !dict.ContainsKey(p.Id)).ToList();
// code B
List<Person> newList = People.Where(p => !ints.Contains(p.Id)).ToList();
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
Console.WriteLine("Number of elements " + newList.Count);
Console.ReadKey();
}
On release mode results are :
Both code A & code B outputs 30 000 elements but :
It took more than 2000 ms with code B and only 5 ms with code A
public class Programm
{
public static void Main()
{
List<ChangesSummary> summaries = new List<ChangesSummary>();
summaries.Add(new ChangesSummary()
{
FieldName = "1",
ProviderKey = "Test1",
});
summaries.Add(new ChangesSummary()
{
FieldName = "2",
ProviderKey = "Test2",
});
summaries.Add(new ChangesSummary()
{
FieldName = "3",
ProviderKey = "Test3",
});
List<string> listProviderKeys = new List<string>();
listProviderKeys.Add("Test1");
listProviderKeys.Add("Test3");
var res = summaries.Where(x => !listProviderKeys.Contains(x.ProviderKey));
res.ToList().ForEach(x => Console.WriteLine(x.ProviderKey));
Console.ReadLine();
}
}
public class ChangesSummary
{
public string TableName { get; set; }
public string ProviderKey { get; set; }
public string ProviderAdrsKey { get; set; }
public string ProviderSpecialtyKey { get; set; }
public string FieldName { get; set; }
}
I think in this case simple Where would be easier and more readable to apply.
var first = new List<string> { "a" };
var second = new List<ChangesSummary>()
{
new ChangesSummary() { ProviderKey = "a" },
new ChangesSummary() { ProviderKey = "b" }
};
var result = second.Where(item => !first.Contains(item.ProviderKey));
// result
// .ToList()
// .ForEach(item => Console.WriteLine(item.ProviderKey));
I believe this will work:
List<ChangesSummary> ExceptionList = SecondList.
Where(x => !ListProviderKeys.Any(key => x.ProviderKey == key)).ToList();

how can I add a value to the list from the Dictionary<int,Object> and the list is in the Object

Ok.. I've seen some similar discussions so I hope this is unique enough.
I would like to initialize and modify data in a List
The list is a Property of the class User, which is inside a Dictionary
http://ideone.com/0YtpnC
internal class User
{
public string ID { get; set; }
public string Name { get; set; }
public List<ContactNumber> AddressBook { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
Dictionary<int, User> dic = new Dictionary<int, User>();
dic.Add(1, new User { ID = "id1", Name = "name1" });
dic.Add(2, new User { ID = "id2", Name = "name2" });
dic.Add(3, new User { ID = "id3", Name = "name3", AddressBook = new List<ContactNumber>(){new ContactNumber(3432),new ContactNumber(3213)} });
User user = dic.Where(z => z.Value.ID == "id3").FirstOrDefault().Value;
Console.WriteLine(user.Name);
DisplayList(user);
//Console.WriteLine(user.AddressBook.ToString());
//update the list
addOrUpdate(dic,3,user);
//var used = new User { ID = "id1", Name = "Harry" };
//dic[1] = used;
user = dic.Where(z => z.Value.ID == "id3").FirstOrDefault().Value;
Console.WriteLine(user.Name);
DisplayList(user);
}
private static void DisplayList(User user)
{
foreach (ContactNumber number in user.AddressBook)
{
Console.WriteLine(number.PhoneNumber);
}
}
//determin list length
public static void addOrUpdate(Dictionary<int, User> dic, int key, User user)
{
//sets a new user data and just replaces it in the dictionary
//var used = new User { ID = "id1", Name = "Harry" };
var used = new User{ ID = "id3", Name = "Henry" ,AddressBook = new List<ContactNumber>(){new ContactNumber(3111),new ContactNumber(4444)}};
if (dic.TryGetValue(key, out user))
{
// yay, value exists!
dic[key] = used;
}
else
{
// darn, lets add the value
dic.Add(key, used);
}
}
}
the problem is I want to get the user info and just add a contact number to the list. Currently it rewrites the entire list since I make a new version of list in the update function.
http://ideone.com/iI2Rxb
Simply:
dic[key].AddressBook.Add(new ContactNumber(666));
This seems to be a solution.
user.AddressBook.Add(new ContactNumber() { PhoneNumber = 121212});
from MSDN Docs
Wont below help, just add to the list (since it is referenced, it will update whatever you have been getting from the dictionary)
user.AddressBook.Add(...new contact number);

String pattern searching in Multidimensional String array [,]

Let's Assume I have Multi dimensional Object array that represents employee information for example
String[,] Employee= new object[,] {
{"john","MBA#MBA#BE#MBA#BE"},
{"jan","MS#MSC#MBA"},
};
Visualize
john MBA#MBA#BE#MBA#BE
jan MS#MSC#MBA
I want remove the duplicated data ( where data is divided by #)
john MBA#BE
jan MS#MSC#MBA
For this scenario it's better to use a dictionary:
Dictionary<string, string> employee = new Dictionary<string, string>()
{
{"john", "MBA#MBA#BE#MBA#BE"},
{"jan", "MS#MSC#MBA"}
}
Dictionary<string, string> result = new Dictionary<string, string>();
foreach (var kvp in employee)
{
result[kvp.Key] = string.Join("#", kvp.Value.Split('#').Distinct());
}
The result dictionary will contain the result:
// Prints "MS#MSC#MBA"
Console.WriteLine(result["jan"]);
// Prints "MBA#BE"
Console.WriteLine(result["john"]);
Personally I'd create a class to hold that information
public class Employee
{
public Employee(string name)
{
Name = name;
Degress = new HashSet<string>();
}
public string Name { get; private set; }
public HashSet<string> Degrees { get; private set; }
}
Then you can populate a list of them like this
string[,] employeeArray = { { "john", "MBA#MBA#BE#MBA#BE" }, { "jan", "MS#MSC#MBA" } };
List<Employee> employees = new List<Employee>();
for (int i = 0; i < employeeArray.GetLength(0); i++)
{
Employee employee = new Employee(employeeArray[i,0]);
foreach (var degree in employeeArray[i, 1].Split('#'))
{
employee.Degrees.Add(degree);
}
employees.Add(employee);
}
foreach (var e in employees)
{
Console.WriteLine(e.Name + " " + string.Join(" ", e.Degress));
}
Which prints
john MBA BE
jan MS MSC MBA
Because Degrees is a HashSet it will not allow duplicates, and when you attempt to pass a duplicate to Add it will just return false.

Create a subset of an object based off an array of property names

I have a class and an array of property names defined as follows:
public class Dog {
public string Name { get; set; }
public string Breed { get; set; }
public int Age { get; set; }
}
var desiredProperties = new [] {"Name", "Breed"};
I also have a method that returns a list of dog objects:
List<Dog> dogs = GetAllDogs();
Is there an way I can return a subset of dogs that only contain the properties defined within the desiredProperties array? Eventually, this resulting list will be serialized to JSON.
I have been struggling with this problem for some time now, considering that the user will be allowed to specify any combination of properties (assuming they are all valid) as the output within the array. Some more examples:
var desiredProperties = new [] {"Name", "Age"};
// Sample output, when serialized to JSON:
// [
// { Name: "Max", Age: 5 },
// { Name: "Spot", Age: 2 }
// ]
var desiredProperties = new [] {"Breed", "Age"};
// [
// { Breed: "Scottish Terrier", Age: 5 },
// { Breed: "Cairn Terrier", Age: 2 }
// ]
you can write a function to do that. Use the extension method below.
public static class Extensions
{
public static object GetPropertyValue(this object obj, string propertyName)
{
return obj.GetType().GetProperty(propertyName).GetValue(obj);
}
public static List<Dictionary<string, object>> FilterProperties<T>(this IEnumerable<T> input, IEnumerable<string> properties)
{
return input.Select(x =>
{
var d = new Dictionary<string, object>();
foreach (var p in properties)
{
d[p] = x.GetPropertyValue(p);
}
return d;
}).ToList();
}
}
Test it like
var dogs = GetAllDogs();
var f1 = dogs.FilterProperties(new[]
{
"Name", "Age"
});
var f2 = dogs.FilterProperties(new[]
{
"Breed", "Age"
});
Console.WriteLine(JsonConvert.SerializeObject(f1));
Console.WriteLine(JsonConvert.SerializeObject(f2));
and result is
[{"Name":"Spot","Age":2},{"Name":"Max","Age":5}]
[{"Breed":"Cairn Terrier","Age":2},{"Breed":"Scottish Terrier","Age":5}]
I don't have a clue if this is the most efficient way to do it, but it's a way of doing it:
var list = new List<Dog>();
list.Add(new Dog {Name = "Max", Breed = "Bull Terrier", Age = 5});
list.Add(new Dog {Name = "Woofie", Breed = "Collie", Age = 3});
var desiredProperties = new[] {"Name", "Breed"};
var exportDogs = new List<Dictionary<string, object>>();
foreach(var dog in list)
{
var exportDog = new Dictionary<string, object>();
foreach(var property in desiredProperties)
{
exportDog[property] = dog.GetType().GetProperty(property).GetValue(dog, null);
}
exportDogs.Add(exportDog);
}
var output = JsonConvert.SerializeObject(exportDogs);
The output will look like this:
[{"Name":"Max","Breed":"Bull Terrier"},{"Name":"Woofie","Breed":"Collie"}]
If, however, you don't need to dynamically access properties, it's a lot better to do something like this:
var output = list.Select(dog => new {dog.Name, dog.Breed});
Then just serialize the output.
something like this...not tested...
var desiredProperties = new [] {"Name", "Breed"};
var lst = (from asm in AppDomain.CurrentDomain.GetAssemblies()
from asmTyp in asm.GetTypes()
where typeof(dog).IsAssignableFrom(asmTyp) && desiredProperties.All(p=> PropertyExists(asmTyp, p))
select asmTyp).ToArray();
private bool PropertyExists(Type dogType, string name)
{
bool ret=true;
try{ dogType.GetProperty(name);}
catch{ret=false};
return ret;
}

Categories

Resources