I have the following data set and would like to store the three arrays in one variable for lookup.
name date size
aaa 201201 0.82
bbb 201306 1.04
ccc 201209 0.91
................
How do I store all the information in one variable? There are hundreds of rows. I am working with C#. I need to be able to search through the variable. For example, if time = 201201, name = aaa, then the size is 0.82.
Best way? Create a wrapper class, store in a List, query using Linq to objects:
public class YourStuff{
public string Name;
public DateTime Date;
public double Size;
}
...
List<Stuff> myStuff = new List<Stuff>();
//then load from DataSet, DataTable, etc.
Some Linq examples:
var greaterThanOne = myStuff.Where(stuff => stuff.Size > 1);
var greaterThanOneCount = myStuff.Count(stuff => stuff.Size > 1);
var sumOfAllSizes = myStuff.Sum(stuff => stuff.Size);
With Linq to objects you can find, sort, slice and dice, group by, you name it.
EDIT: I modified my original answer to be able to search by name and date and get size.
You could use the Tuple class like this:
Dictionary<Tuple<string, DateTime>, float> dict = new Dictionary<Tuple<string, DateTime>, float>();
dict[new Tuple<string, DateTime>("aaa", DateTime.Now)] = 0.82f;
This approach assumes that the combination of name and date is unique, like an index. You can easily search by index, then.
If you need to search name/date by size, though, the wrapper class approach Adrian Carneiro suggested is probably better.
Related
I need help, how do I get MAX datatable column value where value LIKE 'N01%'
Basically, if I convert this to SQL:
SELECT MAX(user) FROM tblUser WHERE user LIKE 'N01%'
Thank you.
You can simply do this:
string[] data = {"hello", "N01jaja", "N01ll"};
var userWithN1 = data.Where(we => we.StartsWith("N01")).Max();
StartsWith checks if the element starts with a certain string.
If there's a class then need to implement IComparable.
Sample code:
public class TestClass : IComparable<string>
{
public string Value { get; private set; }
public int CompareTo(string other) { return Value.CompareTo(other); }
}
var result = foo.tblUser.Where(u => u.user.StartsWith("N01")).Max(u => u.user));
Simply use a where statement to start your filter, use a StartsWith to emulate SQL's xx% pattern. Then use Max on a particular column. Though make sure User is something that will actually have a Max value.
In LINQ, I always find it helpful to break the problem down. Here in this case, you have a list of items, you want to narrow down that list with a WHERE clause and return the MAX of the remaining items.
Start
var myItems = db.GetMyList();
WHERE with LIKE
Assuming User is a string variable
myItems = myItems.Where(x=>x.User.StartsWith("N01"));
MAX
var maxItem = myItems.Max(x=>x.User);
All Together
var maxItem = db.GetMyList().Where(x=>x.User.StartsWith("N01")).Max(x=>x.User);
edit - Per comment below, since the search string was 'N01%', is should be starts with and not contains.
I am fairly new to C#
I am trying to retrieve some information from an external data source and store it in array, once it is in an array I wish to sort it by time.
I know how to do this for just one column in a row, however the information I require has multiple columns.
For example:
foreach (Appointment Appoint in fapts)
{
// Store Appoint.Subject, Appoint.Start, Appoint.Organiser.Name.ToString(), Appoint.Location in an array
}
// Sort my array by Appoint.Start
foreach ( item in myNewArray )
{
//print out Appoint.Subject - Appoint.Start, Appoint.Organiser.Name.ToString() and Appoint.location
}
Many thanks for your help.
EDIT:
I have multiple data sources which pull in this:
foreach (Appointment Appoint in fapts)
{
// Store Appoint.Subject, Appoint.Start, Appoint.Organiser.Name.ToString(), Appoint.Location in an array
}
Hence the need to sort the items in a new array, I know this isn't very efficent but there is no way of getting the information I need in any other way.
You can sort a list using the LINQ sorting operators OrderBy and ThenBy, as shown below.
using System.Linq;
and then...
var appointments = new List<Appointment>();
var sortedAppointments = list.OrderBy(l => l.Subject).ThenBy(l => l.Name).ToList();
This will create a new list of appointments, sorted by subject and then by name.
It's unclear what your final aim is but:
Use a generic List instead of an array:
See this SO question for more information as to why using a List is prefered.
List<Appointment> appointments = new List<Appointment>();
foreach (Appointment Appoint in fapts)
{
appointments.Add(Appoint);
}
foreach (var item in appointments)
{
Console.WriteLine(item.Subject);
Console.WriteLine(item.Foo);
// Here you could override ToString() on Appointment to print eveything in one Console.WriteLine
}
If the aim of your code is to order by time, try the following:
var sortedAppointments = fapts.OrderBy(a => a.Start); // assuming Start is a DateTime property of `Appointment`.
Consider a Dictionary Object instead of an array if the data is conceptually one row multiple columns.
foreach(KeyValuePair<string, string> entry in MyDic)
{
// do something with entry.Value or entry.Key
}
You already have a list of objects in fpts, sort that list itself:
fpts.OrderBy(x => x.Subject).ThenBy(x => x.Location).ToList();
LINQ is your friend here.
fapts appears to already be a collection so you could just operate on it.
var myNewArray = fapts.OrderBy(Appoint => Appoint.Start).ToArray()
I've used the ToArray() call to force immediate evaluation and means that myNewArray is already sorted so that if you use it more than once you don't have to re-evaluate the sort.
Alternatively if you are only using this once you can just as easily miss the ToArray() portion out and then execution of the sort will be deferred until you try and enumerate through myNewArray.
This solution puts the source objects into the array, but if you are just wanting to store the specific fields you mention then you will need to use a select. You have two choices for the array item type, you can either use an anonymous class which provides difficulties if you are returning this array from a function or define a class.
For anonymous:
var myNewArray = fapts.OrderBy(Appoint => Appoint.Start)
.Select(Appoint => new {
Start = Appoint.Start,
Organiser = Appoint.Organiser.Name.ToString(),
Location = Appoint.Location
}).ToArray();
For named class assuming class is MyClass:
var myNewArray = fapts.OrderBy(Appoint => Appoint.Start)
.Select(Appoint => new MyClass {
Start = Appoint.Start,
Organiser = Appoint.Organiser.Name.ToString(),
Location = Appoint.Location
}).ToArray();
You have a wide range of options. The 2 most common are:
1) Create a class, then define an array or list of that class, and populate that
2) Create a structure that matches the data format and create an array or list of that
Of course, you could put the data into an XML format or dataset, but that's probably more work than you need.
public List<foo> appointments = new List<foo>();
public struct foo
{
public string subject ;
public DateTime start ;
public string name ;
public string location ;
}
public void foo1()
{
// parse the file
while (!File.eof())
{
// Read the next line...
var myRecord = new foo() ;
myRecord.subject = data.subject ;
myRecord.start = data.Start ;
myRecord.name = data.Name ;
//...
appointments.Add(myRecord);
}
}
Enjoy
(Since I can't comment and reply to the comment - it wasn't clear if he had a class, etc. or was just showing us what he wanted to do. I assumed it was just for demonstration purposes since there wasn't any info as to how the data was being read. If he could already put it into a class, than the first answer applied anyway. I just tossed the last 2 in there because they were options for getting the data first.)
I have a class in my Windows application like so:
public class Pets
{
String Name {get;set;}
int Amount {get;set;}
}
In one of my other classes i made a List of that class like so.
List<Pets> myPets = new List<Pets>();
myPets.Add(new Pets{ Name = "Fish", Amount = 8});
myPets.Add(new Pets{ Name = "Dogs", Amount = 2});
myPets.Add(new Pets{ Name = "Cats", Amount = 2});
Is there a way i can get the Index of the Pets whos Name = "Fish"?
I realize i can do this
int pos = 0;
for(int x = 0; x<myPets.Count;x++)
{
if( myPets[x].Name == "Fish")
{
pos = x;
}
}
But in the case that i have ALOT of items in myPets it would take long to loop through them to find the one i am looking for. Is there another way to complete the task above. That would make my application run quicker? In the case that myPets has a lot of items in it.
The way you have your data structured at the moment does not lend itself well to searching by pet's name if the list is large.
So iterating manually like you suggest and what FindIndex is doing is known as a linear search which is a brute force algorithm. If you have N items in your collection, the worst case scenario to find an item is N iterations. This is known as O(N) using the Big O Notation. The speed of search grows linearly with the number of items within your collection.
For faster searching you need to change to a different data structure (like a Hashtable), use a database or implement a different search algorithm, such as a binary search( O(log(n)) complexity ).
Have a look at this question for an example:
Can LINQ use binary search when the collection is ordered?
If you want to find index only to access item of List you can use Dictionary instead.
var pets = new Dictionary<string, int>();
pets.Add("Dogs", 2);
pets.Add("Fish", 8);
int amount = pets["Fish"];
What would be the efficient way of sorting typeof(EnumType) alphabetically?
The enum values have index non-sequential however sorted in alphabetic order.
(i.e. apple = 5, banana = 2, cantaloupe = 3)
Instantiating temporarily is fine.
Eventually I need the index code for the specific enum value selected.
I am asking because the method I came up with does not look the best:
Array tmp = Enum.GetValues(typeof(EnumType));
string[] myenum = tmp.OfType<object>().Select(o => o.ToString()).ToArray();
Array.Sort(myenum);
int enum_code = (int)Enum.Parse(typeof(EnumType), myenum.GetValue((int)selected_index).ToString());
string final_code = enum_code.ToString());
You could use Linq to write more compact and maintainable code. Unless you're doing this in the inner loop of a high-performance application, I doubt the speed of Linq vs. your original code vs. any other possible implementation will matter at all:
var sorted = (from e in Enum.GetValues(typeof(EnumType)).Cast<EnumType>()
orderby e.ToString() select e).ToList();
Given the error, a more labourious (and .net 2 compatible) solution is;
SortedDictionary<string, MyEnumType> list = new SortedDictionary<string, MyEnumType>();
foreach (Enum e in Enum.GetValues(typeof(MyEnumType)))
{
list.Add(e.ToString(), (MyEnumType)e);
}
To retrieve the enum;
MyEnumType temp = list["SomeValue"];
I have 2 lists, what are pairs:
List<int> timeStamp = new List<int>();
List<string> ownerStamp = new List<string>();
For example:
timeStamp' elements: 1, 10, 32 ...
ownerStamp' elements: John, Dave, Maria ...
The pairs are: John-1; Dave-10; Maria-32...
I have to order the timestamp list's elements, but i have to hold the context! How can i do it? Manually? Or smthng smart with factory ordering?
There is an overload of Array.Sort() method, which allow you sort one array using other array items as keys. You can convert your lists to arrays, then sort them, and then convert back:
List<int> timeStamp = new List<int>();
List<string> ownerStamp = new List<string>();
int[] timeStampArray = timeStamp.ToArray();
string[] ownerStampArray = ownerStamp.ToArray();
Array.Sort(timeStampArray, ownerStampArray);
timeStamp = new List<int>(timeStampArray);
ownerStamp = new List<string>(ownerStampArray);
You'd probably be better off making a container object, which contains both owner and timestamp, and make it comparable:
class Entry : IComparable<Entry> {
public int TimeStamp { get; set; }
public string Owner { get; set; }
public Entry(int timeStamp, string owner) {
this.TimeStamp = timeStamp;
this.Owner = owner;
}
public int CompareTo(Entry other) {
return this.TimeStamp.CompareTo(other.TimeStamp);
}
}
You could then make a list of these and sort it using the List<T> Sort() method.
To access the timestamp and owner, simply access the TimeStamp and Owner fields of the Entry.
Generally, if you want data to belong together, it's a good idea to explicitly group them together in an object or structure; then the grouping will happen automatically without you needing to take special care to keep things grouped.
Your question doesn't specify exactly what output you're expecting, but the following will give you a sorted collection of Tuple objects, whose first item is the time-stamp and second item is the owner.
timeStamp.Zip(ownerStamp, (i,s) => Tuple.Create(i,s)).OrderBy(t => t.Item1)
Best if you bring the pairs together into a 'SortedDictionary', which will automatically sort the pairs for you, or create a list of tuples for the timeStamp and ownerStamp, and then sort the elements in the tuple list based on the timeStamp key.
A sorted dictionary might help.