0

how to change array into tabular form?

eg:

array = 1 2 3 4 5 6 7 8 9 10 11 12

result

 1 10 11
 2 9  12
 3 8  
 4 7
 5 6 

in this particular order up-down-down-up-up-down

the array is taken from a .txt file and its based on user input so the value varies

here is some of my code

declare -a myarray
# Load file into array.
readarray myarray < temp2.txt
s=$myarray
f  or i in $(seq 0 $((${#s} - 1))); do
        echo "s[$i] = \"${s:$i:1}\""
done
10
  • If the array is of size N, how many rows and columns do you expect in the output? Commented Aug 25, 2014 at 20:51
  • depends, but each column must have 5 element in it, that mean 5 rows just like the table in my earlier post Commented Aug 25, 2014 at 20:56
  • 1
    Your code sample doesn't seem to be an attempt at solving the problem. Commented Aug 25, 2014 at 21:04
  • What does up-down-down-up-up-down mean? Commented Aug 25, 2014 at 21:05
  • @TomFenech It means, I believe, that the output snakes around the columns as opposed to simply being split along columns printing downwards. Commented Aug 25, 2014 at 21:06

4 Answers 4

2

This script does what you want:

#!/bin/bash

a=( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 )
rows=5

for (( j=0; j<rows; ++j )); do 
    for (( i=0; i<=$(( ${#a[@]} / rows )); ++i )); do        
        if (( i%2 )); then idx=$(( (i + 1) / 2 * 2 * rows - j - 1 ))
        else idx=$(( (i / 2) * 2 * rows + j )); fi
        printf "%-4s" "${a[idx]}"
    done
    printf "\n"
done

Output:

1   10  11      
2   9   12      
3   8   13  18  
4   7   14  17  
5   6   15  16 

To make it work from left to right rather than from top to bottom, you can simply swap the i and j loops around (and change the name rows to cols so that it still makes sense):

#!/bin/bash

a=( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 )
cols=5

for (( i=0; i<=$(( ${#a[@]} / cols )); ++i )); do        
    for (( j=0; j<cols; ++j )); do 
        if (( i%2 )); then idx=$(( (i + 1) / 2 * 2 * cols - j - 1 ))
        else idx=$(( (i / 2) * 2 * cols + j )); fi
        printf "%-4s" "${a[idx]}"
    done
    printf "\n"
done

Output:

1   2   3   4   5   
10  9   8   7   6   
11  12  13  14  15  
        18  17  16
Sign up to request clarification or add additional context in comments.

6 Comments

hi. let say i wanted to use same concept but instead of column, i wanted to use in row. so it will be like in 1st row, left to right. 2nd row right to left. so it will be like (1st row)1 2 3 4 5 (2nd row)10 9 8 7 6
No problem. Swap the i and j loops around to make it go horizontally instead. I've updated the answer.
HOLY IT WORKED! thanks a lot mr Tom. I really appreciate your help. +rep
btw another quick question. can i save the output in one string by column order (eg. 1 10 11 12 9 2 3 8 13 .....) ?
I have already answered your original question. I would suggest that you try to change it yourself and if you have any problems, post a new question showing what you've tried and explaining the problem you're having.
|
0
declare -a s
s=(1 2 3 4 5 6 7 8 9 10 11 12)

ofstabled=(9 7 5 3 1)
ofstableu=(1 3 5 7 9)
for ((i=0; i<5;++i)); do
    for ((j=$i; j<${#s[@]};)); do
        printf "%d " ${s[$j]}
    let j=$j+${ofstabled[$i]}
    if [ $j -lt ${#s[@]} ]; then
        printf "%d " ${s[$j]}
        let j=$j+${ofstableu[$i]}
    fi
    done
    printf "\n"
done

You can gussy it up if you want but it works.

Comments

0

Script:

#!/bin/bash

a=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
rows=${1:-5}

col=()
for ((i = 0; i < ${#a[@]}; i++)); do
    ((ind=i % rows))
    (( ((i / rows) % 2 == 0) && (ind = ((rows - 1) - ind)) ))
    [ -n "${col[(rows - 1) - $ind]}" ] && col[(rows - 1) - $ind]+=" "
    col[(rows - 1) - $ind]+=${a[$i]}
done

printf %s\\n "${col[@]}" | column -t

Output:

$ ./order.sh
1  10  11
2  9   12
3  8   13  18
4  7   14  17
5  6   15  16

$ ./order.sh 3
1  6  7  12  13  18
2  5  8  11  14  17
3  4  9  10  15  16

With credit to @TomFenech for the inspiration to make the row count controllable.

Comments

0

You can use awk to read from the file and print it the way you want:

$ awk '{
    if(NR<=5) {
        a[NR]=$0
        next
    } else {
        row=NR%10
    }
}
!(row in a) {
    if(row == 0)
        row++
    else
        row=5 - (NR % 5) + 1
}
{
    a[row]=a[row] FS $0
}
END {
    for(i in a)
        print a[i]
}' file
1 10 11
2 9 12
3 8
4 7
5 6

1 Comment

hi. let say if i wanted to use the same concept in row instead of column. that is its the same snake like sorting, but from left to right in 1st row, right to left in 2nd row, left to right in 3rd row and so on. and the no of rows is based on user input(ill figure this out later)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.