c# Array.FindAllIndexOf which FindAll IndexOf - c#

I know c# has Array.FindAll and Array.IndexOf.
Is there a Array.FindAllIndexOf which returns int[]?

string[] myarr = new string[] {"s", "f", "s"};
int[] v = myarr.Select((b,i) => b == "s" ? i : -1).Where(i => i != -1).ToArray();
This will return 0, 2
If the value does not exist in the array then it will return a int[0].
make an extension method of it
public static class EM
{
public static int[] FindAllIndexof<T>(this IEnumerable<T> values, T val)
{
return values.Select((b,i) => object.Equals(b, val) ? i : -1).Where(i => i != -1).ToArray();
}
}
and call it like
string[] myarr = new string[] {"s", "f", "s"};
int[] v = myarr.FindAllIndexof("s");

You can write something like :
string[] someItems = { "cat", "dog", "purple elephant", "unicorn" };
var selectedItems = someItems.Select((item, index) => new{
ItemName = item,
Position = index});
or
var Items = someItems.Select((item, index) => new{
ItemName = item,
Position = index}).Where(i => i.ItemName == "purple elephant");
Read : Get the index of a given item using LINQ

Searches for an element that matches the conditions defined by the specified predicate, and returns all the zero-based index of the occurrence within the entire System.Array.
public static int[] FindAllIndex<T>(this T[] array, Predicate<T> match)
{
return array.Select((value, index) => match(value) ? index : -1)
.Where(index => index != -1).ToArray();
}

I know this is an old post, but you can try the following,
string[] cars = {"Volvo", "BMW", "Volvo", "Mazda","BMW","BMW"};
var res = Enumerable.Range(0, cars.Length).Where(i => cars[i] == "BMW").ToList();
returns {1,4,5} as a list

No, there is not. But you can write your own extension method.
public static int[] FindAllIndexOf<T>(this T[] a, Predicate<T> match)
{
T[] subArray = Array.FindAll<T>(a, match);
return (from T item in subArray select Array.IndexOf(a, item)).ToArray();
}
and then, for your array, call it.

You can loop with findIndex giving an index
string[] arr = { "abc", "asd", "def", "abc", "lmn", "wer" };
int index = -1;
do
{
index = Array.IndexOf(arr, "abc", index + 1);
System.Console.WriteLine(index);
} while (-1 != index);

I've used Nikhil Agrawal's answer to create the following related method, which may be useful.
public static List<int> FindAllIndexOf<T>(List<T> values, List<T> matches)
{
// Initialize list
List<int> index = new List<int>();
// For each value in matches get the index and add to the list with indexes
foreach (var match in matches)
{
// Find matches
index.AddRange(values.Select((b, i) => Equals(b, match) ? i : -1).Where(i => i != -1).ToList());
}
return index;
}
Which takes a list with values and a list with values that are to be matched. It returns a list of integers with the index of the matches.

You can solve this problem by creating only 2 integer variables. More power to you!
string[] seasons= { "Fall","Spring", "Summer", "Fall", "Fall", "Winter"};
int i = 0;
int IndexOfFallInArray = 0;
int[] IndexesOfFall= new int[seasons.Length];
foreach (var item in seasons)
{
if (item == "Fall")
{
IndexesOfFall[i] = IndexOfFallInArray;
i++;
}
IndexOfFallInArray++;
}

How about simply:
public static IEnumerable<int> Available()
{
for (int i = 0; i < myarr.Length; i++)
{
if (myarr[i] is null) //Your predicate here...
yield return i;
}
}

I'm aware that the question is answered already, this is just another way of doing it. note that I used ArrayList instead of int[]
// required using directives
using System;
using System.Collections;
String inputString = "The lazy fox couldn't jump, poor fox!";
ArrayList locations = new ArrayList(); // array for found indexes
string[] lineArray = inputString.Split(' '); // inputString to array of strings separated by spaces
int tempInt = 0;
foreach (string element in lineArray)
{
if (element == "fox")
{
locations.Add(tempInt); // tempInt will be the index of current found index and added to Arraylist for further processing
}
tempInt++;
}

Related

Is there a function equivalent to "String.IndexOf(String[])"?

Is there any function that returns the index of the first occurrence of ANY string in a given array like: String.IndexOf(String[])?
or do I need a custom function for it?
For example the below function
"AppleBananaCherry".IndexOf(new[] {"Banana", "Cherry"});
and
"AppleBananaCherry".IndexOf(new[] {"Cherry", "Banana"});
returns 5
There is no prepared function but you can use something like this,
var sample = "AppleBananaCherry";
var input = new[] { "Cherry", "Banana" };
var result = input.Min(x => sample.IndexOf(x));
If sample has not any item of input, it returns -1
This should
public static int IndexOf(this string s, string[] values) {
var found = values
.Select(v => s.IndexOf(v))
.Where(index => index >= 0)
.OrderBy(v => v)
.Take(1)
.ToList();
return found.Count > 0 ? found[0] : -1;
}
EDIT: Removing -1 values
There is no built-in function for that, String.IndexOf() method accepts only single string or char as parameter, but you can write your own extension method, which uses IndexOf for every item in array, like in the following sample. It also should correctly exclude -1 from intermediate result
public static class Ext
{
public static int IndexOf(this string thisString, string[] values)
{
var index = thisString.Length;
var isFound = false;
foreach (var item in values)
{
var itemIndex = thisString.IndexOf(item, StringComparison.InvariantCulture);
if (itemIndex != -1 && itemIndex < index)
{
index = itemIndex;
isFound = true;
}
}
return isFound ? index : -1;
}
}
The usage example
var index = "AppleBananaCherry".IndexOf(new[] {"Banana", "Cherry"}); //returns 5
index = "AppleBananaCherry".IndexOf(new[] { "Cherry", "Banana" }); //returns 5

How to sort on 2 distinct rules in List<string>

I need to sort a List<string> following 2 rules.
My string element will always be formatted as XXXnnnnE or XXXnnnnD where X are capitalized letters from A to Z and n are digit from 0 to 9.
I want to sort my list alphabetically, but I want E string to come before D string as shown below
DFG0001D
AWK0007E
ORK0127E
AWK0007D
DFG0001E
ORK0127D
need to be sorted as
AWK0007E
AWK0007D
DFG0001E
DFG0001D
ORK0127E
ORK0127D
How could I achieve this ?
Thanks for help
Here is snippet how you can do this with Linq OrderBy and ThenByDescending operations:
string[] arr = { "DFG0001D", "AWK0007E", "ORK0127E", "AWK0007D", "DFG0001E", "ORK0127D" };
arr = arr
.OrderBy(r => r.Substring(0, 7))
.ThenByDescending(s => s.Substring(7, 1))
.ToArray();
you can use a custom delegate and compare the 1st 3 chars and the last one:
List<string> x = new List<string>();
x.Add("DFG0001D");
x.Add("AWK0007E");
x.Add("ORK0127E");
x.Add("AWK0007D");
x.Add("DFG0001E");
x.Add("ORK0127D");
x.Sort(delegate(string c1, string c2) {
string a = c1.Substring(0, 3)+c1.Substring(c1.Length-1, 1);
string b = c2.Substring(0, 3)+c2.Substring(c2.Length-1, 1);
return (a.CompareTo(b));
});
Console.WriteLine("After sort...");
foreach (string i in x)
{
Console.WriteLine(i);
}
Fiddle example : https://dotnetfiddle.net/YAzvB4
var list = new List<string>{
"DFG0001D",
"AWK0007E",
"ORK0127E",
"AWK0007D",
"DFG0001E",
"ORK0127D"
};
list.Sort((str1, str2) => {
var eq = string.Compare(str1.Substring(0, str1.Length - 1), str2.Substring(0, str2.Length - 1));
if (eq == 0)
eq = string.Compare(str2[str2.Length - 1].ToString(), "E");
return eq;
});
foreach (var str in list)
Console.WriteLine(str);
Output:
AWK0007E
AWK0007D
DFG0001E
DFG0001D
ORK0127E
ORK0127D
just implement your own comparer like this:
class CustomStringComparer : IComparer<string>
{
private readonly IComparer<string> _baseComparer;
public CustomStringComparer(IComparer<string> baseComparer)
{
_baseComparer = baseComparer;
}
public int Compare(string x, string y)
{
// strings are completely same
if (_baseComparer.Compare(x, y) == 0)
{
return 0;
}
// strings are completely same except last char
if (_baseComparer.Compare(x.Substring(0, x.Length - 2), y.Substring(0, y.Length - 2)) == 0)
{
// if last char is E then win
return x.Last() == 'E' ? -1 : 1;
}
// defaut compare everything else
return _baseComparer.Compare(x, y);
}
}
Then you are able doing this:
static void Main(string[] args)
{
List<string> list = new List<string>()
{
"DFG0001D",
"AWK0007E",
"ORK0127E",
"AWK0007D",
"DFG0001E",
"ORK0127D"
};
list.Sort(new CustomStringComparer(StringComparer.CurrentCulture));
foreach (var item in list)
{
Console.WriteLine(item);
}
}
And output is this:
AWK0007E
AWK0007D
DFG0001E
DFG0001D
ORK0127E
ORK0127D

Need help on a simple string sort method from a string array

seriously need some guideline on string sorting methodology. Perhaps, if able to provide some sample code would be a great help. This is not a homework. I would need this sorting method for concurrently checking multiple channel names and feed the channel accordingly based on the sort name/string result.
Firstly I would have the string array pattern something like below:
string[] strList1 = new string[] {"TDC1ABF", "TDC1ABI", "TDC1ABO" };
string[] strList2 = new string[] {"TDC2ABF", "TDC2ABI", "TDC2ABO"};
string[] strList3 = new string[] {"TDC3ABF", "TDC3ABO","TDC3ABI"}; //2nd and 3rd element are swapped
I would like to received a string[] result like below:
//result1 = "TDC1ABF , TDC2ABF, TDC3ABF"
//result2 = "TDC1ABI , TDC2ABI, TDC3ABI"
//result3 = "TDC1ABO , TDC2ABO, TDC3ABO"
Ok, here is my idea of doing the sorting.
First, each of the strList sort keyword *ABF.
Then, put all the strings with *ABF into result array.
Finally do Order sort to have the string array align into TDC1ABF, TDC2ABF, TDC3ABF accordingly.
Do the same thing for the other string array inside a loop.
So, my problem is.. how to search *ABF within a string inside a string array?
static void Main()
{
var strList1 = new[] { "TDC1ABF", "TDC1ABI", "TDC1ABO" };
var strList2 = new[] { "TDC2ABF", "TDC2ABI", "TDC2ABO" };
var strList3 = new[] { "TDC3ABF", "TDC3ABO", "TDC3ABI" };
var allItems = strList1.Concat(strList2).Concat(strList3);
var abfItems = allItems.Where(item => item.ToUpper().EndsWith("ABF"))
.OrderBy(item => item);
var abiItems = allItems.Where(item => item.ToUpper().EndsWith("ABI"))
.OrderBy(item => item);
var aboItems = allItems.Where(item => item.ToUpper().EndsWith("ABO"))
.OrderBy(item => item);
}
If you do something like this then you can compare all the sums and arrange them in order. The lower sums are the ones closer to 1st and the higher are the ones that are farther down.
static void Main(string[] args)
{
string[] strList1 = new string[] { "TDC1ABF", "TDC1ABI", "TDC1ABO" };
string[] strList2 = new string[] { "TDC2ABF", "TDC2ABI", "TDC2ABO" };
string[] strList3 = new string[] { "TDC3ABF", "TDC3ABO", "TDC3ABI" };
arrange(strList1);
arrange(strList2);
arrange(strList3);
}
public static void arrange(string[] list)
{
Console.WriteLine("OUT OF ORDER");
foreach (string item in list)
{
Console.WriteLine(item);
}
Console.WriteLine();
for (int x = 0; x < list.Length - 1; x++)
{
char[] temp = list[x].ToCharArray();
char[] temp1 = list[x + 1].ToCharArray();
int sum = 0;
foreach (char letter in temp)
{
sum += (int)letter; //This adds the ASCII value of each char
}
int sum2 = 0;
foreach (char letter in temp1)
{
sum2 += (int)letter; //This adds the ASCII value of each char
}
if (sum > sum2)
{
string swap1 = list[x];
list[x] = list[x + 1];
list[x + 1] = swap1;
}
}
Console.WriteLine("IN ORDER");
foreach (string item in list)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.ReadLine();
}
If the arrays are guaranteed to have as many elements as there are arrays then you could sort the individual arrays first, dump the sorted arrays into an nxn array and then transpose the matrix.

Replace all occurences of a string from a string array

I have a string array like:
string [] items = {"one","two","three","one","two","one"};
I would like to replace all ones with zero at once.
Then items should be:
{"zero","two","three","zero","two","zero"};
I found one solution How do I replace an item in a string array?.
But it will replace the first occurrence only. Which is the best method/approach to replace all occurrences?
Theres no way to do that without looping.. even something like this loops internally:
string [] items = {"one","two","three","one","two","one"};
string[] items2 = items.Select(x => x.Replace("one", "zero")).ToArray();
I'm not sure why your requirement is that you can't loop.. however, it will always need to loop.
There is one way to replace it without looping through each element:
string [] items = {"zero","two","three","zero","two","zero"};
Other than that, you have to iterate through the array (for/lambda/foreach)
Sorry, you have to loop. There's no getting around it.
Also, all of the other answers give you a new array with the desired elements. If you want the same array to have its elements modified, as your question implies, you should just do it like this.
for (int index = 0; index < items.Length; index++)
if (items[index] == "one")
items[index] = "zero";
Simple.
To avoid writing a loop in your code every time you need this to happen, create a method:
void ReplaceAll(string[] items, string oldValue, string newValue)
{
for (int index = 0; index < items.Length; index++)
if (items[index] == oldValue)
items[index] = newValue;
}
Then call it like this:
ReplaceAll(items, "one", "zero");
You can also make it into an extension method:
static class ArrayExtensions
{
public static void ReplaceAll(this string[] items, string oldValue, string newValue)
{
for (int index = 0; index < items.Length; index++)
if (items[index] == oldValue)
items[index] = newValue;
}
}
Then you can call it like this:
items.ReplaceAll("one", "zero");
While you're at it, you might want to make it generic:
static class ArrayExtensions
{
public static void ReplaceAll<T>(this T[] items, T oldValue, T newValue)
{
for (int index = 0; index < items.Length; index++)
if (items[index].Equals(oldValue))
items[index] = newValue;
}
}
The call site looks the same.
Now, none of these approaches supports custom string equality checking. For example, you might want the comparison to be case sensitive, or not. Add an overload that takes an IEqualityComparer<T>, so you can supply the comparison you like; this is much more flexible, whether T is string or something else:
static class ArrayExtensions
{
public static void ReplaceAll<T>(this T[] items, T oldValue, T newValue)
{
items.ReplaceAll(oldValue, newValue, EqualityComparer<T>.Default);
}
public static void ReplaceAll<T>(this T[] items, T oldValue, T newValue, IEqualityComparer<T> comparer)
{
for (int index = 0; index < items.Length; index++)
if (comparer.Equals(items[index], oldValue))
items[index] = newValue;
}
}
You can also do it in parallel:
Parallel.For(0, items.Length,
idx => { if(items[idx] == "one") { item[idx] = "zero"; } });
string [] items = {"one","two","three","one","two","one"};
items = items.Select(s => s!= "one" ? s : "zero").ToArray();
Found answer from here.
You can try this, but I think, It will do looping also.
string [] items = {"one","two","three","one","two","one"};
var str= string.Join(",", items);
var newArray = str.Replace("one","zero").Split(new char[]{','});
string[] items = { "one", "two", "three", "one", "two", "one" };
If you want it the index way as you specified:
int n=0;
while (true)
{
n = Array.IndexOf(items, "one", n);
if (n == -1) break;
items[n] = "zero";
}
But LINQ would be better
var lst = from item in items
select item == "one" ? "zero" : item;
string[] newarry = items.Select(str => { if (str.Equals("one")) str = "zero"; return str; }).ToArray();

Check if there are no repeats in the list

I have a list called com, which contains a bunch of integers. I need to check the list to make sure that each integer only exists once in the list.
So if:
com{1,2,3,4,1,3}
I need have some code to check that 1 is represented twice as well as 3.
This is my best guess on how to solve it:
for (int j = 0; j < com.Count; j++)
{
if (com.Contains(com[j]))
{
lion += 1;
}
else
{
lion = 0;
}
}
But it doesn't work. Can anybody out there help me??
Here's a simple, but probably not that efficient way using LINQ:
using System.Linq;
...
bool containsRepeats = com.Count() != com.Distinct().Count();
You can determine if a collection contains a duplicate by adding each item to a HashSet<T>. The HashSet<T>.Add Method returns false if the item is already present:
public static bool HasDuplicate<T>(this IEnumerable<T> source)
{
var h = new HashSet<int>();
return source.Any(x => !h.Add(x));
}
If you just want to remove all duplicates from the collection, you can use the Enumerable.Distinct Extension Method:
var result = new[] { 1, 2, 3, 4, 1, 3 }.Distinct();
// result == { 1, 2, 3, 4 }
you can try like this..
int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 };
var duplicates = listOfItems
.GroupBy(i => i)
.Where(g => g.Count() > 1)
.Select(g => g.Key);
foreach (var d in duplicates)
Console.WriteLine(d);
here is for methods to do so:
public static bool LinqAny<T>(IEnumerable<T> enumerable)
{
HashSet<T> set = new();
return enumerable.Any(element => !set.Add(element));
}
public static bool LinqAll<T>(IEnumerable<T> enumerable)
{
HashSet<T> set = new();
return !enumerable.All(set.Add);
}
public static bool LinqDistinct<T>(IEnumerable<T> enumerable)
{
return enumerable.Distinct().Count() != enumerable.Count();
}
public static bool ToHashSet<T>(IEnumerable<T> enumerable)
{
return enumerable.ToHashSet().Count != enumerable.Count();
}

Categories