Suppose I have a list of double values in C# that contains a pair of double values that looks like this:
var ListToSample = new List<double>
{ 49.5353, 49.6241, 49.92432 };
And from these values I want to create a 100 samples. What is the most effective way of doing that.
You could use Enumerable.Repeat:
var hundredSamples = Enumerable.Repeat(ListToSample, 100);
var allLists = new List<List<Double>>(100);
allLists.AddRange(hundredSamples);
or in one line:
var allLists = Enumerable.Repeat(ListToSample, 100).ToList();
Related
I want to add column with data to a deedle dataframe.
I'm doing it this way, and it works, but I believe there should be a better way ?
void addTrendValues(Frame<int, string> df){
List<double> trend_val = new List<double>();
df.FillMissing(0);
List<int> indexes= new List<int>();
for(int i =0; i<1000;i++){
double trendpips = getPipsTilNextTrend(df,i);
trend_val.Add(trendpips);
indexes.Add(i);
if(i% 10000 == 0) { Console.WriteLine(i) ;}
}
df.AddColumn("trend_val",new Series<int, double>(indexes.ToArray(),trend_val.ToArray()));
}
Any idea ?
If you generate IEnumerable<KeyValuePair<K,V>> in some way, then you can use the ToSeries extension method provided by Deedle. The following does that quite nicely using LINQ (but it also removes the printing, which you might want to recover).
var newSeries = Enumerable.Range(0, 1000).Select(i =>
KeyValue.Create(i, getPipsTilNextTrend(df, i))).ToSeries();
df.AddColumn("trend_val", newSeries);
I've a list that pulls timespans and selects and displays the largest timespan in the list. I need to figure out a way to display the name that also matches that timespan. Not exactly sure where to start with this. would anyone be able to get me started. some of the code I've is below.
Code: You can see I create a list of timespans from item where workmodedirectiondescription = AVAIL-IN. I need AgName = AVAIL-IN also = and then to match the agent that has the max time Listoftimespans.max and display the name of the agent that has the max time. I hope this makes sense. The biggest issue I'm having is I can create a separate list of agname but then don't know how to match the times of the agent to display the name that has the largest time. I can't add agname to the list listoftimespans because agname is of type string not timespan.
var listofTimeSpans = new List<TimeSpan>();
List<NewAgent> newAgentList = new List<NewAgent>();
foreach (var item in e.CmsData.Agents)
{
NewAgent newAgents = new NewAgent();
newAgents.AgentName = item.AgName;
newAgents.AgentExtension = item.Extension;
newAgents.AgentDateTimeChange = ConvertedDateTimeUpdated;
newAgents.AuxReasons = item.AuxReasonDescription;
newAgents.LoginIdentifier = item.LoginId;
newAgents.AgentState = item.WorkModeDirectionDescription;
var timeSpanSince = DateTime.Now - item.DateTimeUpdated;
newAgents.AgentDateTimeStateChange = timeSpanSince;
newAgentList.Add(newAgents);
if (item.WorkModeDirectionDescription == "AVAIL-IN")
{
listofTimeSpans.Add(timeSpanSince);
}
var comparetimeandname = new tuple<string, TimeSpan>(item.Agname, listoftimespans.max());
max = comparetimeandname.item2;
maxname = comparetimeandname.item1.
}
Update: occurs right after the above code
var availInAgents = newAgentList.Where(ag => ag.AgentState == "AVAIL-IN").ToList();
availInAgents.Sort((t1, t2)=>t1.AgentDateTimeStateChange.CompareTo(t2.AgentDateTimeStateChange));
var minTimeSpanAgent = availInAgents.FirstOrDefault();
var maxTimeSpanAgent = availInAgents.LastOrDefault();
var min3 = availInAgents.Take(3).ToList();
var max3 = availInAgents.Reverse<NewAgent>().Take(3).ToList();
NextInLine.Text = string.Join(Environment.NewLine, min3);
Edit: screenshot
enter image description here
So let's say, as discussed in comments, you collect a List of tuples representing names and their timespans. By the way, I wouldn't do that in the loop; I'd do this after the loop:
var availInItems =
newAgentList
.Where(ag => ag.WorkModeDirectionDescription == "AVAIL-IN")
.Select(ag =>
new Tuple<String, TimeSpan>(ag.AgentName, ag.AgentDateTimeStateChange))
.ToList();
To get the min and max timespan items, just sort the list by the TimeSpan values of each item, and grab the first and last items. I'm using FirstOrDefault() and LastOrDefault() instead of First() and Last() because they return null on an empty list rather than throwing an exception. That way, we more gracefully handle the case where the list happens to be empty.
List<Tuple<String, TimeSpan>> availInItems = new List<Tuple<string, TimeSpan>>();
// ... populate availInItems in loop ...
availInItems.Sort((t1, t2) => t1.Item2.CompareTo(t2.Item2));
var minTimeSpanTuple = availInItems.FirstOrDefault();
var maxTimeSpanTuple = availInItems.LastOrDefault();
Lowest three, highest three:
var min3 = availInItems.Take(3).ToList();
// There's another overload of Reverse, without the type argument, which
// is a meber of List<T>; it reorders the list in place and returns void.
// You need this one.
var max3 = availInItems.Reverse<Tuple<String, TimeSpan>>().Take(3).ToList();
Those are OK if you have fewer than three items in the list. You'll just get whatever it has.
However
Both pieces of information that we're putting in the tuple are in NewAgent. Why get a tuple involved? No need. I'd just do this:
var availInAgents =
newAgentList
.Where(ag => ag.WorkModeDirectionDescription == "AVAIL-IN")
.ToList();
availInAgents.Sort((t1, t2) =>
t1.AgentDateTimeStateChange.CompareTo(t2.AgentDateTimeStateChange));
var minTimeSpanAgent = availInAgents.FirstOrDefault();
var maxTimeSpanAgent = availInAgents.LastOrDefault();
var min3 = availInAgents.Take(3).ToList();
var max3 = availInAgents.Skip(availInAgents.Count - 3).ToList();
max3.Reverse();
I think LINQ can help you.
For example, if you need the agent with max TimeSpan:
var maxAgent = newAgentList.Max(agnet => agnet.AgentDateTimeStateChange);
Console.writeLine(maxAgent.AgentName);
I have an object with a String field containing a comma separated list of integers in it. I'm trying to use LINQ to retrieve the ones that have a specific number in the list.
Here's my approach
from p in source
where (p.Keywords.Split(',').something.Contains(val))
select p;
Where p.Keywords is the field to split.
I've seen the following in the net but just doesn't compile:
from p in source
where (p.Keywords.Split(',').Select(x=>x.Trim()).Contains(val))
select p;
I'm a LINQ newbie, but had success with simpler queries.
Update:
Looks like I was missing some details:
source is a List containing the object with the field Keywords with strings like 1,2,4,7
Error I get is about x not being defined.
Here's an example of selecting numbers that are greater than 3:
string str = "1,2,3,4,5,6,7,8";
var numbers = str.Split(',').Select(int.Parse).Where(num => num > 3); // 4,5,6,7,8
If you have a list then change the Where clause:
string str = "1,2,3,4,5,6,7,8";
List<int> relevantNums = new List<int>{5,6,7};
var numbers = str.Split(',').Select(int.Parse).Where(num => relevantNums.Contains(num)); // 5,6,7
If you are not looking for number but for strings then:
string str = "1,2,3,4,5,6,7,8";
List<string> relevantNumsStr = new List<string>{"5","6","7"};
var numbers = str.Split(',').Where(numStr => relevantNumsStr.Contains(numStr)); // 5,6,7
Here is an example of how you can achieve this. For simplicity I did to string on the number to check for, but you get the point.
// class to mimic what you structure
public class MyObj
{
public string MyStr{get;set;}
}
//method
void Method()
{
var myObj = new List <MyObj>
{
new MyObj{ MyStr="1,2,3,4,5"},
new MyObj{ MyStr="9,2,3,4,5"}
};
var num =9;
var searchResults = from obj in myObj
where !string.IsNullOrEmpty(obj.MyStr) &&
obj.MyStr.Split(new []{','})
.Contains(num.ToString())
select obj;
foreach(var item in searchResults)
Console.WriteLine(item.MyStr);
}
Thanks for all the answers, although not in the right language they led me to the answer:
from p in source where (p.Keywords.Split(',').Contains(val.ToString())) select p;
Where val is the number I'm looking for.
I have a list of strings:
var list = new List<string>();
list.Add("CAT");
list.Add("DOG");
var listofItems = new List<string>();
listofItems .Add("CATS ARE GOOD");
listofItems .Add("DOGS ARE NICE");
listofItems .Add("BIRD");
listofItems .Add("CATAPULT");
listofItems .Add("DOGGY");
and now i want a function like this:
listofItems.Where(r=> list.Contains(r));
but instead of Contains, i want it to do a starts with check so 4 out of the 5 items would be returned (BIRD would NOT).
What is the fastest way to do that?
You can use StartsWith inside of an Any
listofItems.Where(item=>list.Any(startsWithWord=>item.StartsWith(startsWithWord)))
You can visualize this as a double for loop, with the second for breaking out as soon as it hits a true case
var filteredList = new List<String>();
foreach(var item in listOfItems)
{
foreach(var startsWithWord in list)
{
if(item.StartsWith(startsWithWord))
{
filteredList.Add(item)
break;
}
}
}
return filteredList;
The fastest way would be usage of another data structure, for example Trie. Basic C# implementation can be found here: https://github.com/kpol/trie
This should get you what you need in a more simplified format:
var result = listofItems.Select(n =>
{
bool res = list.Any(v => n.StartsWith(v));
return res
? n
: string.Empty;
}).Where(b => !b.Equals(string.Empty));
The Trie data structure is what you need. Take a look at this more mature library: TrieNet
using Gma.DataStructures.StringSearch;
...
var trie = new SuffixTrie<int>(3);
trie.Add("hello", 1);
trie.Add("world", 2);
trie.Add("hell", 3);
var result = trie.Retrieve("hel");
I am creating a new C# List (List<double>). Is there a way, other than to do a loop over the list, to initialize all the starting values to 0?
In addition to the functional solutions provided (using the static methods on the Enumerable class), you can pass an array of doubles in the constructor.
var tenDoubles = new List<double>(new double[10]);
This works because the default value of an double is already 0, and probably performs slightly better.
You can use the initializer:
var listInt = new List<int> {4, 5, 6, 7};
var listString = new List<string> {"string1", "hello", "world"};
var listCustomObjects = new List<Animal> {new Cat(), new Dog(), new Horse()};
So you could be using this:
var listInt = new List<double> {0.0, 0.0, 0.0, 0.0};
Otherwise, using the default constructor, the List will be empty.
Use this code:
Enumerable.Repeat(0d, 25).ToList();
new List<double>(new double[25]); //Array elements default to 0
One possibility is to use Enumerable.Range:
int capacity;
var list = Enumerable.Range(0, capacity).Select(i => 0d).ToList();
Another is:
int capacity;
var list = new List<double>(new double[capacity]);
A bit late, but maybe still of interest:
Using LINQ, try
var initializedList = new double[10].ToList()
...hopefully avoiding copying the list (that's up to LINQ now).
This should be a comment to Michael Meadows' answer, but I'm lacking reputation.
For more complex types:
List<Customer> listOfCustomers =
new List<Customer> {
{ Id = 1, Name="Dave", City="Sarasota" },
{ Id = 2, Name="John", City="Tampa" },
{ Id = 3, Name="Abe", City="Miami" }
};
from here: David Hayden's Blog