Многомерные массивы - это непрерывный блок памяти, поэтому вам приходится обращаться с ними как с одним массивом. Попробуйте это:
var dict = arr.Cast<string>()
.Select((s, i) => new { s, i })
.GroupBy(s => s.i / arr.GetLength(1))
.ToDictionary(
g => g.First().s,
g => g.Skip(1).Select(i => i.s).ToArray()
);
С пояснениями:
// First, cast it to an IEnumerable<string>
var dict = arr.Cast<string>()
// Use the Select overload that lets us get the index of the element,
// And we capture the element's index (i), along with the element itself (s)
// and put them together into an anonymous type [1]
.Select((s, i) => new { s, i })
// .GetLength(dimension) is a method on multidimensional arrays to
// get the length of a given dimension (pretty self-explanatory)
// In this case, we want the second dimension, or how wide each
// row is: [x,y] <- we want y
// Divide the element index (s.i) by that length to get the row index
// for that element
.GroupBy(s => s.i / arr.GetLength(1))
// Now we have an Grouping<int, IEnumerable<anonymous{string,int}>>
.ToDictionary(
// We don't care about the key, since it's the row index, what we want
// is the string value (the `s` property) from first element in the row
g => g.First().s,
// For the value, we want to skip the first element, and extract
// the string values (the `s` property), and then convert to an array
g => g.Skip(1).Select(i => i.s).ToArray()
);
[1]: см. здесь для документации по анонимным типам.