I have a string array and those includes different types of strings and I would like to separate those values in 2 different arrays.
string[] arr = { "12" , "34-2-2" , "xyz" , "33" , "56-3-4" , "45-4" }
Now I want linq query which gives me "12" , "33" in one and "34-2-2" , "56-3-4" in other array. Rest of the values will be ignored.
var _cust= DbContext.Customer.AsQueryable();
This will contain Id (Int32) and in this I want to add query which return if the customer has "12" , "33" will return that result.
var _cont = DbContext.Contacts.AsQueryable();
This will contain DisplayId (string) and in this I want to add query which return if the customer has "34-2-2" , "56-3-4" will return that result.
How can I write linq query for this?
You can use linq with regex pretty simply to solve this...
string[] arr = {"12", "34-2-2", "xyz", "33", "56-3-4", "45-4"};
var first = arr.Where(v => Regex.IsMatch(v, #"^\d+$")).ToArray();
var second = arr.Where(v => Regex.IsMatch(v, #"^\d+-\d+-\d+$")).ToArray();
Console.WriteLine(string.Join(" ", first));
Console.WriteLine(string.Join(" ", second));
Here is a solution that does what you described. It does not use Regex.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp3
{
class Program
{
static readonly char[] digits = "0123456789".ToCharArray();
static void Main(string[] args)
{
string[] arr = { "12", "34-2-2", "xyz", "33", "56-3-4", "45-4" };
var pair = ProcessInput(arr);
Console.WriteLine(String.Join(", ", pair.Item1));
Console.WriteLine(String.Join(", ", pair.Item2));
var done = Console.ReadLine();
}
static Tuple<string[], string[]> ProcessInput(string[] input)
{
var l1 = new List<string>();
var l2 = new List<string>();
foreach(var item in input)
{
if (ContainsOnlyIntegers(item))
{
l1.Add(item);
continue; // move on.
}
var parts = item.Split('-');
if (parts.Length == 3 && parts.All(part => ContainsOnlyIntegers(part)))
{
//must have 3 parts, separated by hypens and they are all numbers.
l2.Add(item);
}
}
return Tuple.Create(l1.ToArray(), l2.ToArray());
}
static bool ContainsOnlyIntegers(string input)
{
return input.ToCharArray().All(r => digits.Contains(r));
}
}
}
Related
I have array like this, values are string:
var arr1 = new [] { "H", "item1", "item2" };
var arr2 = new [] { "T", "thing1", "thing2" };
var arr3 = new [] { "T", "thing1", "thing2" };
var arr4 = new [] { "END", "something" };
var arr5 = new [] { "H", "item1", "item2" };
var arr6 = new [] { "T", "thing1", "thing2" };
var arr7 = new [] { "T", "thing1", "thing2" };
var arr8 = new [] { "END", "something" };
var allArrays = new [] { arr1, arr2, arr3, arr4, arr5, arr6, arr7, arr8 };
I need to group this in to a new array of arrays, so that one array has arrays that start with H or T. The END records (not included in the results) are the delimiters between each section; each new array starts after an END array.
In the end I would like to have somethng like this:
[
[ [H, item1, item2], [T, thing1, thing2], [T, thing1, thing2] ]
[ [H, item1, item2], [T, thing1, thing2], [T, thing1, thing2] ]
]
I know how I can do this with for each loop, but I'm looking for a cleaner way, possibly using linq. All suggestions are much valued, thank you!
you can try this
List<string[]> list = new List<string[]>();
var newArr = allArrays.Select(a => AddToArr(list, a)).Where(a => a != null);
and helper (this code can be put inline, but it easier to read this way)
private static string[][] AddToArr(List<string[]> list, string[] arr)
{
if (arr[0] != "END")
{
list.Add(arr);
return null;
}
var r = list.ToArray();
list.Clear();
return r;
}
result
[
[["H","item1","item2"],["T","thing1","thing2"],["T","thing1","thing2"]],
[["H","item3","item4"],["T","thing3","thing4"],["T","thing5","thing6"]]
]
So arr1, arr2, etc are string[].
allArrays is a string[][].
I hope you gave a meaningful example. From this example it seems that you want all string[] from allArrays, except the string[] that have a [0] that equals the word "END".
If this is what you want, your result is:
string[][] result = allArrays.Where(stringArray => stringArray[0] != "END");
I need to group this in to a new array of arrays, so that one array has arrays that start with H or T. The END records (not included in the results) are the delimiters between each section; each new array starts after an END array.
This is not exactly the same as I see in your example: what if one of the string arrays in allArrays is an empty array, or if it has the value null values. What if one of the the arrays of strings is empty (= length 0), and what if one of the string arrays doesn't start with "H", nor "T", nor "END"?
Literally you say that you only want the string arrays that start with "H" or "T", no other ones. You don't want string arrays that are null, nor empty string arrays. You also don't want string arrays that start with "END", nor the ones that start with String.Empty, or "A" or "B" or anything else than "H" or "T".
If I take your requirement literally, your code should be:
string[] requiredStringAtIndex0 = new string[] {"H", "T"};
string[][] result = allArrays.Where(stringArray => stringArray != null
&& stringArray.Length != 0
&& requiredStringAtIndex0.Contains(stringArray[0]));
In words: from allArrays, keep only those arrays of strings, that are not null, AND that have at least one element AND where the element at index 0 contains either "H" or "T"
Normally I would use an extension method for grouping runs of items based on a predicate, in this case GroupByEndingWith and then throw away the "END" record, like so:
var ans = allArrays.GroupByEndingWith(r => r[0] == "END")
.Select(g => g.Drop(1).ToArray())
.ToArray();
But, in general, you can use Aggregate to collect items based on a predicate at the expense of comprehension. It often helps to use a tuple to track an overall accumulator and a sub-accumulator. Unfortunately, there is no + operator or Append for List<T> that returns the original list (helpful for expression based accumulation) and since C# doesn't yet have a comma operator equivalent, you need an extension method again or you can use ImmutableList.
Using Aggregate and ImmutableList, you can do:
var ans = allArrays.Aggregate(
(ans: ImmutableList<ImmutableList<string[]>>.Empty, curr: ImmutableList<string[]>.Empty),
(ac, r) => r[0] == "END"
? (ac.ans.Add(ac.curr), ImmutableList<string[]>.Empty)
: (ac.ans, ac.curr.Add(r))
).ans
.Select(l => l.ToArray())
.ToArray();
NOTE: You can also do this with List if you are willing to create new Lists a lot:
var ans = allArrays.Aggregate(
(ans: new List<List<string[]>>(), curr: new List<string[]>()),
(ac, r) => r[0] == "END"
? (ac.ans.Concat(new[] { ac.curr }).ToList(), new List<string[]>())
: (ac.ans, ac.curr.Concat(new[] { r }).ToList())
).ans
.Select(l => l.ToArray())
.ToArray();
Here is a simple implementation.
public static void Main(string[] args)
{
var data = ConvertToArrayOfArray(arr1, arr2, arr3, arrr4, arr5, arr6, arr7, arr8);
}
private string[][] ConvertToArrayOfArray(params string[][] arrs)
{
List<string[]> yoList = new List<string[]>();
arrs.ToList().ForEach(x =>
{
if(!x[0] == "END") yoList.Add(x);
});
return yoList.ToArray();
}
I want to make a string array with values of names and some numbers(which are strings)
i want to pass them into a function that will take the array and then split them into an object jagged array (1 array of strings and 1 array of ints)
the array is:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
and the function looks like this:
public object[][] bloop (string[] bstr)
{
}
whats next?
Your scenario looks like bad design that can cause errors and performance issues. The better way is to change code for using generic List<> or something like that. But in your current problem you can use below code:
public object[][] bloop (string[] bstr)
{
var numbers = new List<int>();
var strings = new List<string>();
var result = new object[2][];
foreach(var str in bstr)
{
int number = 0;
if(int.TryParse(str, out number))
{
numbers.Add(number);
}
else
{
strings.Add(str);
}
}
result[0] = strings.ToArray();
result[1] = numbers.ToArray();
return result;
}
public static object[][] bloop(string[] bstr)
{
object[][] result = new object[2][] { new object[bstr.Length], new object[bstr.Length] };
int sFlag = 0, iFlag = 0, val;
foreach (string str in bstr)
if (int.TryParse(str, out val))
result[1][iFlag++] = val;
else
result[0][sFlag++] = str;
return result;
}
I agree that your requirement sounds odd and should be solved with a different approach. However, this will do what you want:
public T[][] Bloop<T>(T[] items)
{
if (items == null) throw new ArgumentNullException("items");
if (items.Length == 1) return new T[][] { items, new T[] { } };
int firstLength = (int) Math.Ceiling((double)items.Length / 2);
T[] firstPart = new T[firstLength];
Array.Copy(items, 0, firstPart, 0, firstLength);
int secondLength = (int)Math.Floor((double)items.Length / 2);
T[] secondPart = new T[secondLength];
Array.Copy(items, firstLength, secondPart, 0, secondLength);
return new T[][] { firstPart, secondPart };
}
Your sample:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
string[][] result = Bloop(str);
If you need the second array as int[] you could use following:
int[] ints = Array.ConvertAll(result[1], int.Parse);
Linq solution.
You have two groups: first one has items that can be parsed to int and the second group contains all the others, so GroupBy looks quite naturally:
public Object[][] bloop(string[] bstr) {
if (null == bstr)
throw new ArgumentNullException("bstr");
int v;
return bstr
.GroupBy(x => int.TryParse(x, out v))
.OrderBy(chunk => chunk.Key) // let strings be the first
.Select(chunk => chunk.ToArray())
.ToArray();
}
Test:
string[] str = { "toto", "the", "moto", "my", "friend", "12", "13", "14", "99", "88" };
// toto, the, moto, my, friend
// 12, 13, 14, 99, 88
Console.Write(String.Join(Environment.NewLine,
bloop(str).Select(x => String.Join(", ", x))));
I want to return a string of matches found in the array1
public static string[] FindMatchs(string[] array1, string[] array2) {
return array1.Where(x => array2.Contains(x)).ToArray();
}
input:
var a1 = new string[] { "ca", "tr", "stack" };
var a2 = new string[] { "car", "house", "tree", "stackoverflow", "bus" };
the method should return "ca", "tr", "stack"
I made a mistake in my previous code.
Please see below for a working example.
You want to use a combination of .Contains() and .Any() to achieve what you are looking for.
Here is a code example based on your code, that should work (names in signature has been changed for clarity):
public static string[] FindMatchs(string[] array, string[] filter) {
return array.Where(x => filter.Any(y => x.Contains(y))).ToArray();
}
Here is a live example of it:
https://dotnetfiddle.net/HdB79V
You are almost there.. a slight change to the line in you method.
return array1.Where(x => array2.Any(y=>y.Contains(x))).ToArray();
The following example returns matches in two lists:
public class names
{
public int ID {get;set;}
public string Name {get;set;}
}
List<names> l1 = new List<names>();
List<names> l2 = new List<names>();
Populate both list:
for example
Name xyz = new Name()
xyz.id = 1;
xyz.name = "blah";
l1.Add(xyz)
var matches = (from l1 in list1
join l2 in list2 on l1.Name equals l2.Name
select sp).ToList();
OR if you want to use Arrays only
var list1 = new string[] {"xyz", "abc"};
var list2 = new string[] {"abc"};
var matches = list1.Intersect(list2);
foreach (string s in matches)
{
//s will return common
}
How would I loop through two arays using a foreach loop?
I found this previously, but that's for PHP not c#
$images = array('image1', 'image2', ...);
$descriptions = array('description1', 'description2', ...);
foreach (array_combine($images, $descriptions) as $image => $desc) {
echo $image, $desc;
}
my thought is to have something like the following
string[] ValueA = {1,2,3}
string[] ValueB = (a,b,c}
foreach(something here from ValueA && ValueB)
{
methodNameHere(ValueA, ValueB); //method I am calling requires the two values
}
You will be Zip operation that come in .Net 4 in feature. This on link1 and link2 is description.
You will be right something like:
var alpha = new [] { A, B, C, D };
var day = new [] { "s", "s", "m", "t" };
var alphasAndDays = alpha.Zip(day, (n, w) => new { Alpha = n, Day = w });
foreach(var ad in alphasAndDays)
{
Console.WriteLine(aw.Alpha + aw.Day);
}
A simple reiteration can do that:
class Program
{
static void Main(string[] args)
{
string[] setA = new string[3] {"1", "2", "3"};
string[] setB = new string[3] { "a", "b", "c" };
foreach (string val1 in setA) {
foreach (string val2 in setB) {
Program test = new Program();
String printer = test.concatString(val1, val2);
Console.WriteLine(printer);
}
}
Console.ReadLine();
}
public string concatString(string value1, string value2) {
String value3 = value1 + value2;
return value3;
}
}
int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
foreach (var item in numbersAndWords)
Console.WriteLine(item);
// This code produces the following output:
// 1 one
// 2 two
// 3 three
Say we have 5 string arrays as such:
string[] a = {"The","Big", "Ant"};
string[] b = {"Big","Ant","Ran"};
string[] c = {"The","Big","Ant"};
string[] d = {"No","Ants","Here"};
string[] e = {"The", "Big", "Ant", "Ran", "Too", "Far"};
Is there a method to compare these strings to each other without looping through them in C# such that only a and c would yield the boolean true? In other words, all elements must be equal and the array must be the same size? Again, without using a loop if possible.
You can use Linq:
bool areEqual = a.SequenceEqual(b);
Try using Enumerable.SequenceEqual:
var equal = Enumerable.SequenceEqual(a, b);
if you want to get array data that differ from another array you can try .Except
string[] array1 = { "aa", "bb", "cc" };
string[] array2 = { "aa" };
string[] DifferArray = array1.Except(array2).ToArray();
Output:
{"bb","cc"}
If you want to compare them all in one go:
string[] a = { "The", "Big", "Ant" };
string[] b = { "Big", "Ant", "Ran" };
string[] c = { "The", "Big", "Ant" };
string[] d = { "No", "Ants", "Here" };
string[] e = { "The", "Big", "Ant", "Ran", "Too", "Far" };
// Add the strings to an IEnumerable (just used List<T> here)
var strings = new List<string[]> { a, b, c, d, e };
// Find all string arrays which match the sequence in a list of string arrays
// that doesn't contain the original string array (by ref)
var eq = strings.Where(toCheck =>
strings.Where(x => x != toCheck)
.Any(y => y.SequenceEqual(toCheck))
);
Returns both matches (you could probably expand this to exclude items which already matched I suppose)
if (a.Length == d.Length)
{
var result = a.Except(d).ToArray();
if (result.Count() == 0)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("NO");
}
}
else
{
Console.WriteLine("NO");
}