Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm a begginer to C# programmer and I have a problem in my code with one string.
I want to know how I can convert this string:
x = {"1","2","0",",","1","2","1",",","1","2","2"}
into something like this:
x = {"120","121","122"}
The variable x is assigned as string and I want it assigned as int. The purpose of this is to get how many numbers are between lets say 120 and 130, which in my string would be 3.
Many Thanks.
string[] x = { "1", "2", "0", ",", "1", "2", "1", ",", "1", "2", "2" };
int[] y = string.Join(string.Empty, x)
.Split(',')
.Select(s => int.Parse(s))
.ToArray();
I think you can do this in three lines as follows:
var x = new []{"1", "2", "0", ",", "1", "2", "1", ",", "1", "2", "2"};
var fullString = String.Join("", x, 0, x.Length);
// get as a string array:
// x = fullString.Split(new[] {','});
// get as an integer array:
var intArray = (fullString.Split(new[] {','}))
.Select(_ => Int32.Parse(_)).ToArray();
In steps this is (1) create the string, (2) join the string, (3) split the string on the separator (which appears to be the comma in your case).
Best of luck!
Not sure why you want to do this but never the less it can be achieved quite simply using LINQ to Objects basic String methods.
var x = new string[] { "1", "2", "0", ",", "1", "2", "1", ",", "1", "2", "2" };
var y = String.Join(String.Empty, x).Split(',');
foreach (var s in y)
Console.WriteLine(s);
Update 23/05/2014
As per the comments, here is some code that will do what you want (i.e. count the numbers between the range 120-130 inclusive).
var min = 120;
var max = 130;
var count = y
.Select(o => Int32.Parse(o))
.Count(o => (min <= o) && (o <= max));
Console.WriteLine(count);
You should first add the 3 strings together to get the correct "120","121","122" as a string
Then you could use a forloop or something equivalent to do val.toint();
EDIT:
Changing a list from list String to Int and keeping the same variable seems abit unnecessary to me
string[] x = { "1", "2", "0", ",", "1", "2", "1", ",", "1", "2", "2" };
StringBuilder sb = new StringBuilder();
foreach (var item in x)
{
sb.Append(item);
}
string str = sb.ToString();
string[] myArr = str.Split(',');
int[] numArr = new int[myArr.Length];
for (int i = 0; i < myArr.Length; i++)
{
numArr[i] = int.Parse(myArr[i]);
}
with a bit of effort, youll be able to find this,(you are not supposed to just post a question, next time do some research please) but whilst the question is here any way:
string[] items;
items = new string[5];
int[] intitems;
intitems = new int[5];
foreach (string item in items)
{
int i = 0;
int.TryParse(items[i], out intitems[i]);
}
an easy and understandable way of doing it. the loop pretty much explains it self
Here is an approach using several string methods and LINQ:
string[] x = { "1", "2", "0", ",", "1", "2", "1", ",", "1", "2", "2" };
string all = string.Join("", x); // "120,121,122"
string[] parts = all.Split(','); // { "120", "121", "122" }
int i = int.MinValue; // variable which is used in below query
int[] y = parts // LINQ query
.Where(s => int.TryParse(s.Trim(), out i)) // filters out invalid strings
.Select(s => i) // selects the parsed ints
.ToArray(); // creates the final array
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 need to get the set subtraction of two string arrays while considering duplicates.
Ex:
var a = new string[] {"1", "2", "2", "3", "4", "4"};
var b = new string[] {"2", "3"};
(a - b) => expected output => string[] {"1", "2", "4", "4"}
I already tried Enumerable.Except() which returns the unique values after subtract: { "1", "4" } which is not what I'm looking for.
Is there a straightforward way of achieving this without a custom implementation?
You can try GroupBy, and work with groups e.g.
var a = new string[] {"1", "2", "2", "3", "4", "4"};
var b = new string[] {"2", "3"};
...
var subtract = b
.GroupBy(item => item)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count());
var result = a
.GroupBy(item => item)
.Select(chunk => new {
value = chunk.Key,
count = chunk.Count() - (subtract.TryGetValue(chunk.Key, out var v) ? v : 0)
})
.Where(item => item.count > 0)
.SelectMany(item => Enumerable.Repeat(item.value, item.count));
// Let's have a look at the result
Console.Write(string.Join(", ", result));
Outcome:
1, 2, 4, 4
By leveraging the undersung Enumerable.ToLookup (which allows you to create dictionary-like structure with multi-values per key) you can do this quite efficiently. Here, because key lookups on non-existent keys in an ILookup return empty IGrouping (rather than null or an error), you can avoid a whole bunch of null-checks/TryGet...-boilerplate. Because Enumerable.Take with a negative value is equivalent to Enumerable.Take(0), we don't have to check our arithmetic either.
var aLookup = a.ToLookup(x => x);
var bLookup = b.ToLookup(x => x);
var filtered = aLookup
.SelectMany(aItem => aItem.Take(aItem.Count() - bLookup[aItem.Key].Count()));
Try the following:
var a = new string[] { "1", "2", "2", "3", "4", "4" }.ToList();
var b = new string[] { "2", "3" };
foreach (var element in b)
{
a.Remove(element);
}
Has been tested.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a list<strings[]> doc and I want to store their counts into a Tuple<string[], int[]> (unique words, number of n words in each list entry). So far I only got the unique strings
public class Program
{
public static void Main(string[] args)
{
List<string[]> doc = new List<string[]>();
string[] a = { "That", "is", "a", "cat" };
string[] b = { "That", "bat", "flew","over","the", "cat" };
doc.Add(a);
doc.Add(b);
string[] strs = doc
.SelectMany(array => array)
.Distinct()
.ToArray();
foreach (string val in strs) {
Console.WriteLine(val);
}
}
}
So the output should be something like
string[] a = { "That","is","a","cat","bat","flew","over"," the" };
int[] i_one = { 1,1,1,1,0,0,0,0 };
int[] i_two ={ 1,0,0,1,1,1,1,1 };
List<Tuple<string[],int[]> ret = new List<string[],int[]>();
var b = new Tuple<string[],int[]>(a, i_one);
var c = new Tuple<string[],int[]>(a, i_two);
ret.Add(b);
ret.Add(c);
So something like (forgive my naming conventions its a hack)
string[] a = { "That", "is", "a", "cat" };
string[] b = { "That", "bat", "flew", "over", "the", "cat" };
var c = a.Union(b).Distinct();
var a1 = (from ch in c select a.Count(r => r == ch));
var b1 = (from ch in c select b.Count(r => r == ch));
Not 100% sure this will solve your issue completely but I knocked this up using LinqPad, but your end result is quite difficult to achieve:
List<string[]> doc = new List<string[]>();
string[] a = { "That", "is", "a", "cat" };
string[] b = { "That", "bat", "flew","over","the", "cat" };
doc.Add(a);
doc.Add(b);
doc.SelectMany(array => array)
.GroupBy(x => x)
.Select(x=> new {Value = x.Key, Count = x.Count()});
Result:
You can do this:
var lines = new List<string[]>
{
new[] { "That", "is", "is", "a", "cat" },
new[] { "That", "bat", "flew", "over", "the", "flew", "cat" }
};
var distinctWords = lines.SelectMany(strings => strings).Distinct().ToArray();
var result = (
from line in lines
let lineWords = line.ToArray()
let counts = distinctWords.Select(distinctWord => lineWords.Count(word => word == distinctWord)).ToArray()
select new Tuple<string[], int[]>(distinctWords, counts)
).ToList();
See demo.
This question already has answers here:
How do I remove duplicates from a C# array?
(28 answers)
Closed 7 years ago.
I got an array
string [] strings = new string[] {"1", "2", "2", "2", "1"};
You can see the value of the array is just 1 and 2, just 2 values, you could say, and I want to get those value out...What I did is here, just a start:
string[] strings = new[] { "1", "2", "2", "2", "1"};
int[] ints = strings.Select(x => int.Parse(x)).ToArray();
I don't what is next...Anyone helps?
You mean you just want an array int[] {1, 2}?
string[] strings = new[] { "1", "2", "2", "2", "1"};
int[] ints = strings.Select(int.Parse).Distinct().ToArray();
You may simply add a distinct to get the unique values:
int[] ints = strings.Select(x => int.Parse(x)).Distinct().ToArray();
Thus your array contains the elements {1, 2}
Classic way:
string[] strings = new[] { "1", "2", "2", "2", "1" };
List<int> items = new List<int>();
for (int i = 0; i < strings.Length; i++)
{
int item = int.Parse(strings[i]);
if (!items.Contains(item))
items.Add(item);
}
I will add the values in the String[] in to the Arraylist. But, I want to access those string values from the ArrayList.
I tried this way.
private void Form1_Load()
{
fr = new string[5] { "1", "2", "3", "4", "5" };
bd = new string[5] {"a", "b","c", "d", "e"};
m = new ArrayList();
dosomething();
}
private void dosomething()
{
string[] record = new string[3];
for (int i = 0; i < 5; i++)
{
record[0] = "1";
record[1] = fr[i];
record[2] = bd[i];
m.Add(record);
}
}
I don't want to use the for loop is that any other way to do this???
I recommend you to use dictionaries. It is in my opinion the quickest way to store / access data. Also, with arraylists, at runtime, it performs a dynamic transtyping, which makes you loose so much time.
You maybe want to use :
fr = new string[5] { "1", "2", "3", "4", "5" };
bd = new string[5] { "a", "b", "c", "d", "e" };
m = new ArrayList();
fr.ToList().ForEach(_item => m.Add(new String[]{ "1", _item,bd[fr.ToList().IndexOf(_item)]}));
But I would prefere a solution like Fares already recommented...Use A Dictionary
Dictionary - MSDN
Not sure why you need an ArrayList. A generic list might be more suitable for you.
var fr = new string[5] { "1", "2", "3", "4", "5" };
var bd = new string[5] {"a", "b","c", "d", "e"};
int i = 1;
var results = fr.Zip<string, string, string[]>(bd, (a,b) => {
var v = new string [3] { i.ToString(), a,b };
i++;
return v;
}).ToList();