I have a collection I want to transform into a dictionary. Here's the code:
myCollection.ToDictionary(item => item.Split('=')[0], item => item.Split('=')[1]);
Being the collection something like:
{"a=312d","b=dw234","c=wqdqw3=3")
The problem comes at the third object. As you can see, it has a second equal inside of it. This one, and all the character after it, are also part of the value (in the dictionary it should be c:wqdqw3=3). But, as you can imagine, I'm getting something like this in my dictionary a:312d, b:dw234, c:wqdqw3.
How could you change it so that the value of the dictionary was, for each element of the collection, everything that comes after the first '='?
IndexOf() and Substring() should help here
string[] input = { "a=312d", "b=dw234", "c=wqdqw3=3" };
var result = input.ToDictionary(x => x.Substring(0, x.IndexOf('=')),
x => x.Substring(x.IndexOf('=') + 1));
Related
Below is my string array. I got this .Where code online and I found it really interesting and I tried modifying it to make it add a character instead of removing a character. However I keep getting the "Method Name Expected error under the 'indexremove' variable on the last line.
Is there any solution to this problem? Or is my modification not able to work?
string[] TestArray = {"a", "b", "c", "d", "e"};
int indexremove = 0; // for removing the character in the 1st position; a.
TestArray = TestArray.Where((source, index) => index != indexremove).ToArray(); //source, index points to the array's character collection, and index != indexremove causes A to be removed from the index of the array. Then it is converted to an array.
foreach (string value in TestArray) {Console.WriteLine(value); //displays output of new array without "a" }
string indextoadd = "a"; //trying to re-add the character back in to the array
TestArray = TestArray.Where((source, index) => index + indexremove(indextoadd)).ToArray(); //Method Name Expected on indexremove
Where doesn't work like this. It's a filtering device so it intrinsically cannot be used to extend/add to a list of things. The only thing you can do with a Where is prevent one of the input items being output, if some test returns false
For any given list of items;
string[] testArray = {"a", "b", "c", "d", "e"};
You can write a Where, and pass to the Where a small nugget of code (we tend to refer to it as a lambda) that is like a nameless method. It must accept one or two arguments and it must return a bool. Where will loop over the input list of items, calling the lambda you passed on each one of the items. If the lambda returns true, the inputted item is output. If it returns false, the list item being looped is not output
These are the conceptual equivalents:
//this nice short thing
testArray.Where(s => s.Length == 1);
//is like this longer thing
public bool LengthIs1(string s){
return s.Length == 1;
}
...
foreach(var s in testArray)
if(LengthIs1(s))
output s; //this is a pretend thing: `output` doesn't exist but it means I don't also have to explain yield return. Just imagine that it sends the value out and carries on looping
Examples
testArray.Where(s => true); //every item will be output
testArray.Where(s => false); //no item will be output
testArray.Where(s => s == "a"); //only items equal to "a" will be output
testArray.Where(s => s.StartsWith("b")); //only items starting with b will be output
testArray.Where(s => DateTime.Now.DayOfWeek == DayOfWeek.Tuesday); //every item will be output if it's Tuesday, otherwise no item will be output
Those are examples that just take one argument s, to the lambda. There is another form, the one you're using, where the lambda can have two parameters - the first parameter is again the item from the array. The second parameter is the index of the item in the array
testArray.Where((s,index) => true); //every item will be output
testArray.Where((s,index) => index == 0); //only the first item will be output
testArray.Where((s,index) => index != 1); //everything apart from the second item will be output
testArray.Where((s,index) => index%2 == 0); //even indexed items will be output
As you can see there isn't any scope for extending or adding more items. You start with 100 items, you can only output somewhere between 0 and 100 items
In the code you posted the first item is filtered out because the lambda assessed index versus index to remove, and will return true (keep) in all cases where they're not the same, and return false (remove) when they are the same
If you want to output more items you have to use something else, like Concat
new[]{1,2}.Concat(new[]{3,4})
This will output an enumeration of 1,2,3,4
Because Where produces an enumerable thing, and Concat can be called on an enumerable thing and accepts as a parameter another enumerable thing it means we could do something like:
testArray
.Where((s,index) => index != indextoremove)
.Concat(
testArray.Where((s,index) => index == indextoremove)
)
The first Where excludes only the indextoremove (it keeps the rest) and the second Where keeps only the indextoremove (it excludes the rest). The Concat would just effectively take the first sequence, where "a" has been excluded and then concatenate on the second sequence where "a" is the only one included. This would essentially move "a" from the start, to the end of the sequence
It's horrifically inefficient, but this example is more about learning
(source, index) => index + indexremove(indextoadd)
This is, alas, flat out a syntax error. You've made indextoadd a string, and index to remove is an int. you can't follow an int variable name with a ( because you cannot execute/call an int. You this also cannot execute an int passing a string to it. As the final nail in the lambda's coffin, it's supposed to return a bool but you've done something approaching a numeric result, if int + int(string) was even possible. In full method terms you've done something like:
public bool AMethod(string source, int index){
string indextoadd = "a";
int indexremove = 1;
return index + indexremove(indextoadd);
}
Which hopefully you can see has a lot of syntax and logical problems..
using System;
using System.Linq;
namespace Problems
{
class Program
{
static void Main(string[] args)
{
string[] TestArray = { "a", "b", "c", "d", "e" };
int indexremove = 1;
var RemovedIndex = TestArray.Skip(indexremove);
foreach(var t in RemovedIndex)
{
Console.WriteLine(t);
}
RemovedIndex.ToList().Insert(indexremove, "a");
RemovedIndex = TestArray.ToArray();
foreach (var t in RemovedIndex)
{
Console.WriteLine(t);
}
}
}
}
Since Arrays are fixed, I opted to skip over the first index in the array. Print the first console to see that the first character is skipped.
Then, since you needed the character back, I converted the current array to a list and inserted the character back. Remember to convert it back to an array afterward.
See the result by running the second loop.
I have an array of strings and I have to take only those entries, which
are starting with "81" or "82". I've tried it like this:
var lines = File.ReadAllLines(fileName); // This returns an array of strings
lines = lines.TakeWhile(item => item.StartsWith("81") ||item.StartsWith("82")).ToArray();
but this just doesn't work. It retuns an empty string array.
When I loop through lines with a for-loop and compare everytime
if (!firstline.Substring(0, 2).StartsWith("81")) continue;
and then I take the required entries, it's working just fine.
Any suggestions how to get it right with LINQ?
You need to use Where():
lines = lines.Where(item => item.StartsWith("81") || item.StartsWith("82")).ToArray();
TakeWhile will take sequence until condition becomes false, but Where will continue and find all elements matching the condition.
I need to find the index of an item in an array of strings where that item's value matches a certain pattern.
Example array & values:
string[] stringArray = { "roleName","UserID=000000","OtherID=11111" }
I need to get the index of the item whose value begins with "UserID=". I know I could iterate through the array and match each value to a regex, but that just sounds slow and messy. I was thinking of doing something like this:
int indexIneed = Array.IndexOf(stringArray,"\bUserID=");
But I've never really had to mess with regular expressions before, so I fumbling around like a toddler. Is there I way I can accomplish what I'm tring to do in O(n) or am I going to have to resort to iteration?
FindIndex will give you what you want:
int indexIneed = Array.FindIndex(stringArray,s => s.StartsWith("UserID="));
I was wondering if there is a way in an ArrayList that I can search to see if the record contains a certain characters, If so then grab the whole entire sentence and put in into a string. For Example:
list[0] = "C:\Test3\One_Title_Here.pdf";
list[1] = "D:\Two_Here.pdf";
list[2] = "C:\Test\Hmmm_Joke.pdf";
list[3] = "C:\Test2\Testing.pdf";
Looking for: "Hmmm_Joke.pdf"
Want to get: "C:\Test\Hmmm_Joke.pdf" and put it in the Remove()
protected void RemoveOther(ArrayList list, string Field)
{
string removeStr;
-- Put code in here to search for part of a string which is Field --
-- Grab that string here and put it into a new variable --
list.Contains();
list.Remove(removeStr);
}
Hope this makes sense. Thanks.
Loop through each string in the array list and if the string does not contain the search term then add it to new list, like this:
string searchString = "Hmmm_Joke.pdf";
ArrayList newList = new ArrayList();
foreach(string item in list)
{
if(!item.ToLower().Contains(searchString.ToLower()))
{
newList.Add(item);
}
}
Now you can work with the new list that has excluded any matches of the search string value.
Note: Made string be lowercase for comparison to avoid casing issues.
In order to remove a value from your ArrayList you'll need to loop through the values and check each one to see if it contains the desired value. Keep track of that index, or indexes if there are many.
Then after you have found all of the values you wish to remove, you can call ArrayList.RemoveAt to remove the values you want. If you are removing multiple values, start with the largest index and then process the smaller indexes, otherwise, the indexes will be off if you remove the smallest first.
This will do the job without raising an InvalidOperationException:
string searchString = "Hmmm_Joke.pdf";
foreach (string item in list.ToArray())
{
if (item.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
{
list.Remove(item);
}
}
I also made it case insensitive.
Good luck with your task.
I would rather use LINQ to solve this. Since IEnumerables are immutable, we should first get what we want removed and then, remove it.
var toDelete = Array.FindAll(list.ToArray(), s =>
s.ToString().IndexOf("Hmmm_Joke.pdf", StringComparison.OrdinalIgnoreCase) >= 0
).ToList();
toDelete.ForEach(item => list.Remove(item));
Of course, use a variable where is hardcoded.
I would also recommend read this question: Case insensitive 'Contains(string)'
It discuss the proper way to work with characters, since convert to Upper case/Lower case since it costs a lot of performance and may result in unexpected behaviours when dealing with file names like: 文書.pdf
If you have a string of "1,2,3,1,5,7" you can put this in an array or hash table or whatever is deemed best.
How do you determine that all value are the same? In the above example it would fail but if you had "1,1,1" that would be true.
This can be done nicely using lambda expressions.
For an array, named arr:
var allSame = Array.TrueForAll(arr, x => x == arr[0]);
For an list (List<T>), named lst:
var allSame = lst.TrueForAll(x => x == lst[0]);
And for an iterable (IEnumerable<T>), named col:
var first = col.First();
var allSame = col.All(x => x == first);
Note that these methods don't handle empty arrays/lists/iterables however. Such support would be trivial to add however.
Iterate through each value, store the first value in a variable and compare the rest of the array to that variable. The instant one fails, you know all the values are not the same.
How about something like...
string numArray = "1,1,1,1,1";
return numArrray.Split( ',' ).Distinct().Count() <= 1;
I think using List<T>.TrueForAll would be a slick approach.
http://msdn.microsoft.com/en-us/library/kdxe4x4w.aspx
Not as efficient as a simple loop (as it always processes all items even if the result could be determined sooner), but:
if (new HashSet<string>(numbers.Split(',')).Count == 1) ...