Using select information from array - c#

I have a string array of the form [a b, a b, a b,...] and I want to create a new array of just the b values. I have tried a .split(" ") but it keeps coming up with an index outside the bounds of the array error.
for (int sequence = 0; sequence < FileIndex.Length; sequence++)
{
string[] SplitIndex = FileIndex[sequence].Split(' ');
sequence++;
WriteLine(SplitIndex[sequence]);
}

for (int sequence = 0; sequence < FileIndex.Length; sequence++)
{
string[] SplitIndex = FileIndex[sequence].Split(' ');
sequence++;
WriteLine(SplitIndex[1]);
}
Once you split, in the SplitIndex you will have 2 elements: "a" and "b". If you want to access "b" you will have to use SplitIndex[1]. You are currently using SplitIndex[sequence]
Also, you have sequence++ twice. One in the for statement, and one inside the loop. You should remove it from the loop.

You could also use LINQ here:
using System.Linq;
...
var stringArray = new string[] { "a b", "a b", "a b" };
var result = stringArray
.Select(str => str.Split(' ').Last())
.ToArray();
Console.WriteLine("{ " + string.Join(", ", result) + " }");
// { b, b, b }
Explanation:
Select every element in the array with Enumerable.Select()
Split each string with String.Split() and take the last element with Enumerable.Last(). You could also just index the second element with [1] here as well.
Convert the result to an array with List.ToArray(). Optionally you could just leave the result as an IEnumerable<string> as well.

for way
Remove sequence++;
Change WriteLine(SplitIndex[sqequence]); to WriteLine(SplitIndex[1]);
for (int sequence = 0; sequence < FileIndex.Length; sequence++)
{
string[] SplitIndex = FileIndex[sequence].Split(' ');
//sequence++;
WriteLine(SplitIndex[1]);
}
Linq way
//Note: no error handling
var bees = FileIndex.Select(fi => fi.Split(' ')[1]);
You can add error handling
var bees = test.Select(fi => fi.Split(' ', StringSplitOptions.RemoveEmptyEntries).Skip(1).FirstOrDefault() ?? "'No b!'" );
Test
var test = new string[] { "a a", "a b", "a c", "a ", "" };
var bees = test.Select(fi => fi.Split(' ', StringSplitOptions.RemoveEmptyEntries).Skip(1).FirstOrDefault() ?? "'No b!'" );
Console.WriteLine(string.Join(" ", bees));
a b c 'No b!' 'No b!'

Related

Sorting a list in c# (custom defined sorting rules)

I have a list of string called choosedGroupList consisting of 5 items. Each item represents a group,
For example: L1andL4 means that L1 will be grouped with L4.
Another example: L1,L4andL5,L6 means that the group L1,L4 will be grouped with the group L5,L6
I am trying to sort this list to be like this:
L1andL4
L5andL6
L1,L4andL5,L6
L2andL1,L4,L5,L6
L3andL2,L1,L4,L5,L6
So I wrote this code to perform this task,
//sorting choosedGroupList
for (int k = 0; k < choosedGroupList.Count; k++)
{
for (int j = k + 1; j < choosedGroupList.Count; j++)
{
string[] parts = choosedGroupList[j].Split(new string[] { "and" }, StringSplitOptions.None);
if (parts[0] == choosedGroupList[k].Replace("and", ",") || parts[1] == choosedGroupList[k].Replace("and", ","))
{
string[] parts2 = choosedGroupList[k + 1].Split(new string[] { "and" }, StringSplitOptions.None);
//if (parts[0] != parts2[0] || parts[1] != parts2[1])
//{
String Temp = choosedGroupList[k + 1];
choosedGroupList[k + 1] = choosedGroupList[j];
choosedGroupList[j] = Temp;
//}
}
}
}
I have no exceptions in the code but, I do not get the desired results.
After executing the code this is the result:
L1andL4
L1,L4andL5,L6
L2andL1,L4,L5,L6
L5andL6
L3andL2,L1,L4,L5,L6
Assumption 1: you wish to sort first by number of 'L's then by the numbers following the 'L's.
The major issue in the code given is that you never check the length of the arrays, so L1,L4 will always sort before L5 because L1 sorts before L5.
If you split on 'and' separately from ',' and sort on length of the array split from ',' first before sorting on the contents of that array, then it should match your proposed sort order.
How about using a Dictionary?
public static Dictionary<string, int> YourDictionary()
{
Dictionary<string, int> returnDict = new Dictionary<string, int>();
returnDict.Add("L1andL4", 1);
returnDict.Add("L5andL6", 2);
returnDict.Add("L1,L4andL5,L6", 3);
returnDict.Add("L2andL1,L4,L5,L6", 4);
returnDict.Add("L3andL2,L1,L4,L5,L6", 5);
return returnDict;
}
Then iterate over the Dictionary:
var theDictionary = clsProdDesign.YourDictionary();
var items = from pair in theDictionary orderby pair.Value ascending select pair;
foreach (KeyValuePair<string, int> pair in items)
{
//do whatever
}

How to get found characters by order from string and keep duplicates to add it to the list without overwriting of previous

I'm tying to find characters from given list for each word of string separately, but I can't figure out how in my case to get found character by order exist in word and keep repeated characters.
For example, if list to find is: var findChar = new List<string> { "a", "i", "t", "e", "c" };
So if word "associates" with my output is [a i t e c] my desired result should be [a c i a t e] by sequence (A)sso(c)(i)(a)(t)(e)s
Here is my code, can you help me find out how can I get desired result for this outputs:
using System;
using System.Collections.Generic;
using System.Linq;
namespace _01_WORKFILE
{
class Program
{
static void Main(string[] args)
{
var findChar = new List<string> { "a", "i", "t", "e", "c" };
List<string> displist = findChar;
Console.WriteLine("Search for chars: [{0}]", string.Join(", ", displist));
int wordNumCount = 0;
char[] delimiterChars = { ' ', ',', '.', ':', '\t' };
string text = "Offices of Runciter Associates";
string[] words = text.Split(delimiterChars);
Console.WriteLine("In string (" + text + ") consisting of (" + words.Length + ") words: ");
foreach (string s in words)
{
if (findChar.Any(s.Contains))
{
wordNumCount++;
var foundChar = string.Join(" ", findChar.Where(ch => s.Contains(ch)));
Console.WriteLine("(" + wordNumCount + ") [" + s + "] [" + foundChar + "]");
}
else
{
wordNumCount++;
var foundChar = string.Join(" ", findChar.Where(ch => s.Contains(ch)));
Console.WriteLine("(" + wordNumCount + ") [" + s + "] [ _ ]");
}
}
Console.Read();
}
}
}
and then also for ultimate output I want get all this sequences of found character from each word to combine it all in one string separated with spaces and underscore where char is no found.
So not sure but I guess I have to add it to the temporary list which must collect results at the end of cycle to be attache to variable
I've tried this way, but seems like it overwrite new add over the previous:
if (findChar.Any(s.Contains))
{
wordNumCount++;
var foundChar = string.Join(" ", findChar.Where(ch => s.Contains(ch)));
List<string> tempList = new List<string>();
tempList.Add(foundChar);
Console.WriteLine("To result output: [{0}]", string.Join(", ", tempList));
}
else
{
wordNumCount++;
var foundChar = string.Join(" ", findChar.Where(ch => s.Contains(ch)));
List<string> tempList = new List<string>();
tempList.Add(foundChar);
Console.WriteLine("To result output: [{0}]", string.Join(", ", tempList));
}
Current output:
Search for chars: [a, i, t, e, c]
In string (Offices of Runciter Associates) consisting of (4) words:
(1) [Offices] [i e c]
(2) [of] [ _ ]
(3) [Runciter] [i t e c]
(4) [Associates] [a i t e c]
Desired output:
Search for chars: [a, i, t, e, c]
In string (Offices of Runciter Associates) consisting of (4) words:
(1) [Offices] [i c e]
(2) [of] [ _ ]
(3) [Runciter] [c i t e]
(4) [Associates] [a c i a t e]
Result output: [ice _ cite aciate]
Here is one way to do it:
var finalOutputStrings = new List<string>();
foreach (string word in words)
{
wordNumCount++;
// Lowercase the input word to recognise capitals
var s = word.ToLower();
// List to store the found characters
var foundChar = new List<char>();
// Iterate around each char in the word to retain the desired order
foreach (var character in s.Where(c => findChar.Contains(c.ToString())))
{
foundChar.Add(character);
}
// Part of the output string containing the found characters
var charString = (foundChar.Count > 0) ? string.Join(" ", foundChar) : " _ ";
Console.WriteLine($"({wordNumCount}) [{word}] [{charString}]");
finalOutputStrings.Add(charString.Replace(" ", ""));
}
var outputString = string.Join(" ", finalOutputStrings);
Console.WriteLine($"Result output: [{outputString}] ");
The final output strings are stored in finalOutputStrings, which is added to after each word is evaluated.
Notice that for each evaluated word, I am iterating around each character within the word to retain the order in which those characters appear.
Output
Search for chars: [a, i, t, e, c]
In string (Offices of Runciter Associates) consisting of (4) words:
(1) [Offices] [i c e]
(2) [of] [ _ ]
(3) [Runciter] [c i t e]
(4) [Associates] [a c i a t e]
Result output: [ice _ cite aciate]
Hope that helps let me know if you have any questions or suggestions.

Join List of strings trailing values don't require delimiters if the right most value is null

What im trying to achieve, but cant get my head around is if i have a list of strings say:
{"test","","data","","123","44"}
this should be joined by a character:
test::data::123:44
but if the list at the end is empty dont delimiter it
{"test","","data","","",""}
should be:
test::data
{"test","","","","",""}
should be:
test
{"test","","","","","44"}
should be:
test::::44
however the list can be of varying lengths which adds another level of complexity.
Just exclude the trailing empty elements from the list Count and then Join the remaining using Take:
List<string> input = ...;
int count = input.Count;
while (count > 0 && string.IsNullOrEmpty(input[count - 1]))
count--;
var output = string.Join(":", input.Take(count));
Using the List<T> specific FindLastIndex method, it can be reduced to the following "one liner":
var output = string.Join(":",
input.Take(input.FindLastIndex(s => !string.IsNullOrEmpty(s)) + 1));
First, with your array:
test = test.Where(x => !string.IsNullOrEmpty(x)).ToArray();
where "test" is your array.
then:
string.Join("::", test);
EDIT:
If you're getting your array of strings by splitting another string, consider the following:
string[] strs = myString.split(someDelimeter, StringSplitOptions.RemoveEmptyEntries);
Start by identifying the last element you want, then slice your list and join as you normally would:
var lastElementIndex = strings.Select((s, index) => string.IsNullOrEmpty(s) ? -1 : index).Max();
var prefix = strings.Take(lastElementIndex + 1);
var result = string.Join(":", prefix);
var obj = {"test","","data","","123","44"};
var count = obj.Count;
for (var i = count - 1; i > -1; i--)
{
if (obj[i]==String.Empty) {
obj.RemoveAt(i);
}
else break;
}
var arr = obj.Split(new char[] { ','}, StringSplitOptions.RemoveEmptyEntries);
var output = arr.Join(":", arr);

How to merge values of two lists together

For example I have:
public static List<int> actorList = new List<int>();
public static List<string> ipList = new List<string>();
They both have various items in.
So I tried joining the values (string and int) together using a foreach loop:
foreach (string ip in ipList)
{
foreach (int actor in actorList)
{
string temp = ip + " " + actor;
finalList.Add(temp);
}
}
foreach (string final in finalList)
{
Console.WriteLine(finalList);
}
Although looking back at this, this was pretty stupid and obviously will not work, as the first forloop is nested.
My expected values for finalList list:
actorListItem1 ipListItem1
actorListItem2 ipListItem2
actorListItem3 ipListItem3
and so on..
So the values from the two lists are concatenated with each other - corresponding of their position in the lists order.
Use ZIP function of LINQ
List<string> finalList = actorList.Zip(ipList, (x,y) => x + " " + y).ToList();
finalList.ForEach(x=> Console.WriteLine(x)); // For Displaying
OR combine them in one line
actorList.Zip(ipList,(x,y)=>x+" "+y).ToList().ForEach(x=>Console.WriteLine(x));
What about some functional goodness?
listA.Zip(listB, (a, b) => a + " " + b)
Assuming you can use .NET 4, you want to look at the Zip extension method and the provided example:
int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
// The following example concatenates corresponding elements of the
// two input sequences.
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
foreach (var item in numbersAndWords)
Console.WriteLine(item);
Console.WriteLine();
In this example, because there is no corresponding entry for "4" in words, it is omitted from the output. You would need to do some checking to make sure the collections are the same length before you start.
Loop over the indexes:
for (int i = 0; i < ipList.Count; ++i)
{
string temp = ipList[i] + " " + actorList[i];
finalList.Add(temp);
}
You may also want to add code before this to verify that the lists are the same length:
if (ipList.Count != actorList.Count)
{
// throw some suitable exception
}
for(int i=0; i<actorList.Count; i++)
{
finalList.Add(actorList[i] + " " + ipList[i]);
}

Counting substring occurrences in string[]

Given a String array such as this:
string[]={"bmw"," ","1bmw"," "};
I need to count how often the substring bmw occurs in that array. In this example it occurs 2 times.
How do I write that in C#?
also i want to ignore the capital character,
sting[]={"bmw", "", "BMw","1bmw"}
then the count result is 3.
what should i do?
#
Thanks for everyone's answer.
Try:
var str = new string[] { "bmw", " ", "1bmw", " " };
var count = str.Count(s => s.Contains("bmw"));
the next code will return the count of case insensitive occurrences (as author mentioned in comments):
var count = str.Count(s =>
s.IndexOf("bmw", StringComparison.OrdinalIgnoreCase) > -1
);
More about string comparisons could be found here.
Without LINQ
int counter = 0;
foreach(string item in string_array)
{
if(item.IndexOf("bmw") > -1){
counter++;
}
}
You can use Linq for this like so:
var s = new string[] {"bmw", "1bmw"};
var result = s.Where(o=>o.Contains("bmw")).Count();
If you're using C# 3, you can use LINQ:
var strings = {"bmw"," ","1bmw"," "};
var count = string.Where( s => s.IndexOf( "bmw" ) > -1 ).Count();
Otherwise a loop will work too:
string[] strings = {"bmw"," ","1bmw"," "};
int count = 0;
foreach( string s in strings ) {
if( s.IndexOf( "bmw" > -1 ) ) {
count++;
}
}
One method using LINQ
static int CountOfString(IEnumerable<string> items, string substring, bool isCaseSensitive)
{
StringComparison comparison = StringComparison.InvariantCulture;
if (!isCaseSensitive)
comparison = StringComparison.InvariantCultureIgnoreCase;
return items.Count(item => item.IndexOf(substring, comparison) > -1);
}
Using it
string[] items = { "bmw", " ", "1bmw", " " };
int count = CountOfString(items, "bmw", false);
Case-insensitiveness makes it a little more verbose but still it's quite compact using following:
var str = new sting[]={"bmw", "", "BMw","1bmw"};
var count = str.Count(s => s.IndexOf("bmw", StringComparison.InvariantCultureIgnoreCase) > -1);

Categories