Indexing the tensor might work.
I assume the initialization of k_block should be outside the first loop?
Otherwise, you would throw away the first results.
Based on this assumption, this code should work:
# Setup
B, H, K = 2, 3, 4
N, M = 5, 6

indices = torch.randint(0, N, (B, H, K))
x = torch.randn(B, N, M)

# Your approach
k_block = []
for j in range(H):
    

    # for K
    for i in range(K):
        # b, 1
        index = indices[:, j, i]
        k_block.append(x[range(B), index])

    # b, KM
k_block = torch.cat(k_block, dim=-1) 

# Indexing approach
x1 = x.clone()
res = x1[torch.arange(B).unsqueeze(1).unsqueeze(2), indices].view(B, -1)

# Test
print((k_block - res).abs().max())
> tensor(0.)