C
C#2y ago
BenMcLean

❔ LINQ build an array with an arbitrary value at the start

So, I want to make a palette that's an array of ints where index 0 is equal to 0 and the rest repeat a rainbow pattern.
public static readonly ReadOnlyCollection<int> Rainbow = Array.AsReadOnly(new int[7]
{ // Just a color test, not a political statement.
unchecked((int)0xFF0000FF),//Red
unchecked((int)0xFFA500FF),//Orange
unchecked((int)0xFFFF00FF),//Yellow
0x00FF00FF,//Green
0x0000FFFF,//Blue
0x4B0082FF,//Indigo
unchecked((int)0x8F00FFFF)//Violet
});
public static int[] RainbowPalette()
{
int[] palette = new int[byte.MaxValue];
for (int index = 1; index < palette.Length; index++)
palette[index] = Rainbow[(index - 1) % Rainbow.Count];
return palette;
}
public static readonly ReadOnlyCollection<int> Rainbow = Array.AsReadOnly(new int[7]
{ // Just a color test, not a political statement.
unchecked((int)0xFF0000FF),//Red
unchecked((int)0xFFA500FF),//Orange
unchecked((int)0xFFFF00FF),//Yellow
0x00FF00FF,//Green
0x0000FFFF,//Blue
0x4B0082FF,//Indigo
unchecked((int)0x8F00FFFF)//Violet
});
public static int[] RainbowPalette()
{
int[] palette = new int[byte.MaxValue];
for (int index = 1; index < palette.Length; index++)
palette[index] = Rainbow[(index - 1) % Rainbow.Count];
return palette;
}
Question: How could I get this same result with LINQ?
23 Replies
Angius
Angius2y ago
Working with HSV colors would be the easiest, since you'd only need to increment the hue
BenMcLean
BenMcLeanOP2y ago
The colors aren't the point, it's a LINQ question
Angius
Angius2y ago
Well, assuming HSV...
var colors = Enumerable.Range(0, 255)
.Select(hue => new Hsv(hue, 255, 255))
.ToArray();
var colors = Enumerable.Range(0, 255)
.Select(hue => new Hsv(hue, 255, 255))
.ToArray();
BenMcLean
BenMcLeanOP2y ago
That isn't the same result. That would return an IEnumerable<HSV>. The question is how to return an int[] Also, that doesn't include the 0 value at the start.
Angius
Angius2y ago
It would return Hsv[] strictly speaking And I thought the colors weren't the point?
BenMcLean
BenMcLeanOP2y ago
The 0 value at the start is the point
Angius
Angius2y ago
Uh, Enumerable.Range(0, someMaxValue) will give you integers from 0 to some max value...?
BenMcLean
BenMcLeanOP2y ago
See, my for loop starts with 1. It leaves index zero blank, then it repeats the rainbow pattern from 1 to 255,
ero
ero2y ago
So start at 1 instead of 0?
Angius
Angius2y ago
If so, Enumerable.Range(1, max) Ah, wait, then 1 would be at index 0 and you don't want that
BenMcLean
BenMcLeanOP2y ago
I guess I could check it like Enumerable.Range(0,255).Select(i => i == 0 ? 0 : Rainbow[(i - 1) % Rainbow.Count]) but it seems like there should be some kind of way to do something like .Add(0).Add(Enumerable.Range(1, 255).Select(i => Rainbow[i % Rainbow.Count]) and then it could concatonate the zero at the start before getting into the range ... maybe?
Angius
Angius2y ago
Generate a list of colors, then list.Insert(0, 0) Will insert 0 at the start of the list and shift everything else up
BenMcLean
BenMcLeanOP2y ago
Oh, OK, that makes sense.
Angius
Angius2y ago
So
var colors = Enumerable.Range(0, 255)
.Select(x => Rainbow[x % Rainbow.Count])
.ToList()
.Insert(0, 0);
var colors = Enumerable.Range(0, 255)
.Select(x => Rainbow[x % Rainbow.Count])
.ToList()
.Insert(0, 0);
Something like this
ero
ero2y ago
Insert doesn't return the list
BenMcLean
BenMcLeanOP2y ago
that except 254, because otherwise you end up with a list that's 257 items long
Angius
Angius2y ago
Ah, right
ero
ero2y ago
Honestly anything i think of makes me fall back to "this would be better if it's just a loop"
BenMcLean
BenMcLeanOP2y ago
I went with
public static readonly int[] RainbowPalette =
Enumerable.Range(0, byte.MaxValue)
.Select(i => i == 0 ? 0 : Rainbow[(i - 1) % Rainbow.Count])
.ToArray();
public static readonly int[] RainbowPalette =
Enumerable.Range(0, byte.MaxValue)
.Select(i => i == 0 ? 0 : Rainbow[(i - 1) % Rainbow.Count])
.ToArray();
actually I went with LINQ because I didn't want it to be a method just wanted it to be a data member if that makes sense
ero
ero2y ago
Bad thinking, stop doing that
D.Mentia
D.Mentia2y ago
That works. I agree, better as a loop. And also we could find a thousand ways to do it, increasingly complex 😛 Like if you took the Math.Sign of i and multiplied it by the value, no conditional You can populate your data member via a method. You want it to be a method because it makes it much easier to change it later, if you want the colors to be different or come in from somewhere else, and because realistically all of these are just really confusing looking
ero
ero2y ago
I would just
private int[]? _palette;
public int[] Palette
{
get
{
if (_palette is not null)
return _palette;

_palette = new int[255];
// rainbow thing, loop, populate

return _palette;
}
}
private int[]? _palette;
public int[] Palette
{
get
{
if (_palette is not null)
return _palette;

_palette = new int[255];
// rainbow thing, loop, populate

return _palette;
}
}
Make it readonly or whatever if you need
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server