DEV Community

Cristian Sifuentes
Cristian Sifuentes

Posted on

Arrays 101 for LLM Power Users — From Basics to “Token‑Efficient Thinking” (with C# Examples)

Arrays 101 for LLM Power Users — From Basics to “Token‑Efficient Thinking” (with C# Examples)

Arrays 101 for LLM Power Users — From Basics to “Token‑Efficient Thinking” (with C# Examples)

Arrays are one of those “basic” topics everyone thinks they already know… until they start building with LLMs.

Then suddenly you care about things like:

  • Why does a slice allocate?
  • How can I format data so the model “gets it” with fewer tokens?
  • Why does chunking work better with fixed-size windows?
  • How do arrays relate to vector embeddings, context windows, and retrieval?

In this post we’ll refresh core array fundamentals and then connect them to how you use LLMs effectively: prompt design, chunking strategies, memory layout intuition, and performance patterns in .NET.

You’ll leave with:

  • A clean mental model of arrays (1D, 2D, jagged)
  • Practical patterns (search, map, filter, reduce)
  • The “LLM lens”: chunking, token budget, structured serialization
  • Token-efficient formatting patterns (arrays → compact text)
  • Performance + memory notes (cache friendliness, allocations, bounds checks)
  • GitHub-ready C# examples and pro tips

Table of Contents

  • Mental Model: What an Array really is
  • Array Basics in C#: creation, indexing, length
  • 1D vs 2D vs Jagged: when to use which
  • Traversal patterns: loops, foreach, Span
  • Common algorithms: search, copy, resize, sort
  • Arrays for LLM work: chunking, windows, embeddings prep
  • Token-efficient formatting: arrays → compact text
  • Performance notes: cache, bounds checks, allocations
  • Production checklist

1) Mental Model: What an Array really is

An array is:

A contiguous block of memory containing elements of the same type, accessible by index.

Key properties:

  • Fixed size once created
  • O(1) random access by index
  • Strong memory locality → CPU cache friendly
  • In .NET, T[] is a reference type object that contains:
    • an object header
    • the array length
    • the contiguous element region

When you index arr[i], the runtime does:

1) bounds check (unless optimized away)

2) address calculation: base + i * sizeof(T)

3) load/store

This is why arrays are extremely fast.


2) Array Basics in C

2.1 Create arrays

int[] numbers = { 1, 2, 3, 25 };
string[] names = new[] { "Juan", "Luis", "Diana" };
var zeros = new int[10]; // fixed length, initialized to 0
Enter fullscreen mode Exit fullscreen mode

2.2 Indexing and length

Console.WriteLine(numbers[0]);     // 1
Console.WriteLine(numbers.Length); // 4
numbers[1] = 200;                  // update
Enter fullscreen mode Exit fullscreen mode

2.3 Bounds checks

// throws IndexOutOfRangeException
// Console.WriteLine(numbers[999]);
Enter fullscreen mode Exit fullscreen mode

Modern JIT can remove bounds checks in tight loops, but only when it can prove safety.


3) 1D vs 2D vs Jagged Arrays (and why it matters)

3.1 One-dimensional (T[])

Best default: compact, fast, simple.

3.2 Rectangular multi-dimensional (T[,])

True 2D grid:

int[,] grid = new int[3, 4];
grid[1, 2] = 99;
Enter fullscreen mode Exit fullscreen mode

Tradeoff: indexing costs can be higher than T[] because the runtime must compute offsets for multiple dimensions.

3.3 Jagged (T[][])

Array of arrays:

int[][] jagged = new int[3][];
jagged[0] = new[] { 1, 2 };
jagged[1] = new[] { 3, 4, 5 };
jagged[2] = new[] { 6 };
Enter fullscreen mode Exit fullscreen mode

Tradeoff: not contiguous across rows, but often faster and more flexible than [,] for “rows of variable length”.

LLM note: jagged arrays map well to “chunks of chunks”: document → paragraphs → sentences.


4) Traversal Patterns

4.1 for loop (fastest control)

for (int i = 0; i < numbers.Length; i++)
{
    Console.WriteLine(numbers[i]);
}
Enter fullscreen mode Exit fullscreen mode

4.2 foreach (clean)

foreach (var n in numbers)
{
    Console.WriteLine(n);
}
Enter fullscreen mode Exit fullscreen mode

4.3 Span: “array view” without allocations

Span<int> window = numbers.AsSpan(1, 2); // slice [numbers[1], numbers[2]]
window[0] = 777;
Enter fullscreen mode Exit fullscreen mode

This is gold for performance and for chunking windows (more on that soon).


5) Common Array Algorithms (you’ll use these everywhere)

5.1 Linear search (O(n))

static int IndexOf<T>(T[] arr, T value)
{
    for (int i = 0; i < arr.Length; i++)
        if (EqualityComparer<T>.Default.Equals(arr[i], value))
            return i;

    return -1;
}
Enter fullscreen mode Exit fullscreen mode

5.2 Copy

var copy = new int[numbers.Length];
Array.Copy(numbers, copy, numbers.Length);
Enter fullscreen mode Exit fullscreen mode

5.3 Sort

Array.Sort(numbers);
Enter fullscreen mode Exit fullscreen mode

5.4 Resize (allocates new array)

Array.Resize(ref numbers, numbers.Length + 10);
Enter fullscreen mode Exit fullscreen mode

Arrays are fixed-size. Resizing means: allocate new → copy → replace reference.


6) Arrays for LLM Work: Chunking, Sliding Windows, and Token Budgets

Here’s the big unlock: LLMs operate over sequences (tokens). Arrays are your tool for structuring sequences before you serialize to prompts.

6.1 Chunking documents into arrays

When you chunk a document for RAG:

  • You split the text into segments (chunks)
  • Each chunk becomes an element in string[] chunks
  • You embed those chunks into vectors

Why arrays? Because they give you:

  • deterministic order
  • stable indices / IDs
  • fast slicing into windows

Example:

string[] chunks = ChunkByChars(text, chunkSize: 1200, overlap: 200);
Enter fullscreen mode Exit fullscreen mode

6.2 Sliding window (overlap) is literally array slicing

LLMs need overlap to keep context continuity:

  • chunk 0: chars 0..1200
  • chunk 1: chars 1000..2200
  • chunk 2: chars 2000..3200

That overlap is a window concept — which maps directly to Span<T> windows.

6.3 Chunking is a “locality” strategy

Chunking works because:

  • you reduce irrelevant noise
  • you feed the model compact, relevant context
  • you stay within context window limits

Arrays make chunking reproducible, testable, and performant.


7) Token‑Efficient Formatting: Arrays → Compact Text That Models Understand

Most people waste tokens by dumping unstructured text.

Instead, treat your prompt like a compact serialization problem.

7.1 Bad: long prose

“Here is a bunch of data, please analyze it…”

7.2 Better: compact array-of-records

If you have call records, store them in an array of small lines:

var lines = new[]
{
    "t=2025-12-10; dir=in; dur=19.0; skill=",
    "t=2025-12-10; dir=out; dur=40.2; skill=sales"
};
Enter fullscreen mode Exit fullscreen mode

Then in prompt:

Records:
[0] t=2025-12-10; dir=in; dur=19.0; skill=
[1] t=2025-12-10; dir=out; dur=40.2; skill=sales
Task: summarize anomalies, compute avg duration, list missing skills.
Enter fullscreen mode Exit fullscreen mode

This works because:

  • the model sees consistent structure
  • tokens are minimized
  • indices are stable → you can reference records by [i]

7.3 A practical “LLM-ready array serializer”

static string ToLLMLines(string[] items, string header = "Items:")
{
    var sb = new System.Text.StringBuilder();
    sb.AppendLine(header);
    for (int i = 0; i < items.Length; i++)
        sb.AppendLine($"[{i}] {items[i]}");
    return sb.ToString();
}
Enter fullscreen mode Exit fullscreen mode

8) Performance Notes That Actually Matter

8.1 CPU cache friendliness

Arrays are contiguous → better cache locality → faster loops.

This matters when you:

  • compute embeddings
  • pre-process large corpora
  • normalize tokens
  • batch requests

8.2 Allocation awareness

  • Array.Resize allocates
  • string.Split allocates
  • LINQ can allocate (enumerators, closures, intermediate collections)

For high-volume pipelines, prefer:

  • Span<T> / ReadOnlySpan<T>
  • ArrayPool<T>
  • simple loops

8.3 Bounds-check elimination

JIT can remove bounds checks in patterns like:

for (int i = 0; i < arr.Length; i++) { /* arr[i] */ }
Enter fullscreen mode Exit fullscreen mode

But if you index with non-obvious expressions, the JIT may keep checks.


9) A GitHub‑Ready C# Deep Dive Example (Arrays + “LLM Thinking”)

Below is a compact example you can drop into a repo to demonstrate:

  • arrays
  • chunking
  • overlap
  • serialization for prompts
using System;
using System.Collections.Generic;
using System.Text;

public static class LlmArrayPatterns
{
    public static void Demo()
    {
        string text = new string('A', 3000); // pretend this is a big document
        var chunks = ChunkByChars(text, chunkSize: 1200, overlap: 200);

        Console.WriteLine($"Chunks: {chunks.Length}");
        Console.WriteLine(ToLLMLines(chunks, header: "Chunk Preview:"));
    }

    // Basic chunker: (size, overlap) -> array of chunks.
    public static string[] ChunkByChars(string input, int chunkSize, int overlap)
    {
        if (chunkSize <= 0) throw new ArgumentOutOfRangeException(nameof(chunkSize));
        if (overlap < 0 || overlap >= chunkSize) throw new ArgumentOutOfRangeException(nameof(overlap));

        var list = new List<string>();
        int step = chunkSize - overlap;

        for (int start = 0; start < input.Length; start += step)
        {
            int len = Math.Min(chunkSize, input.Length - start);
            list.Add(input.Substring(start, len));
            if (start + len >= input.Length) break;
        }

        return list.ToArray();
    }

    // Prompt-friendly formatter: stable indices.
    public static string ToLLMLines(string[] items, string header = "Items:")
    {
        var sb = new StringBuilder();
        sb.AppendLine(header);

        for (int i = 0; i < items.Length; i++)
        {
            var preview = items[i].Length > 40 ? items[i].Substring(0, 40) + "..." : items[i];
            sb.AppendLine($"[{i}] len={items[i].Length} :: {preview}");
        }

        return sb.ToString();
    }
}
Enter fullscreen mode Exit fullscreen mode

10) Production Checklist

Before you build an LLM pipeline with “arrays everywhere”:

  • [ ] Keep raw text chunks in string[] or List<string> (then freeze to array)
  • [ ] Use consistent chunk size + overlap
  • [ ] Preserve indices / IDs for traceability
  • [ ] Serialize arrays into token-efficient formats (indexed lines)
  • [ ] Avoid unnecessary allocations in hot paths (use Span, pooling)
  • [ ] Write tests: chunk boundaries, overlap correctness, stable ordering

Wrap‑up

Arrays are the simplest data structure — but they’re also:

  • the foundation of fast memory access
  • the mental model behind windows and chunking
  • the backbone of token-efficient prompt inputs

If you want, I can also generate:

  • A full .NET 8 console repo with these demos
  • A BenchmarkDotNet suite (arrays vs LINQ vs Span)
  • A “RAG chunking spec” template for your team docs

Happy building — and may your prompts be compact and your arrays cache-friendly. 🧠⚡

Top comments (1)

Collapse
 
shemith_mohanan_6361bb8a2 profile image
shemith mohanan

Loved how you connected basic array concepts to real LLM use cases like chunking, token efficiency, and prompt structuring. The Span + sliding window explanation was especially practical. Great bridge between fundamentals and modern AI workflows.