1

I have two arrays of fruits and corresponding prices. I want to search for a fruit in the fruits array and use the found index to get the price using the prices array.

@echo off
setlocal enabledelayedexpansion

set "fruits[0]=6"
set "fruits[1]=Apple"
set "fruits[2]=Banana"
set "fruits[3]=Orange"
set "fruits[4]=Grapes"
set "fruits[5]=Mango"
set "fruits[6]=Pineapple"

set "prices[0]=6"
set "prices[1]=10"
set "prices[2]=30"
set "prices[3]=25"
set "prices[4]=15"
set "prices[5]=12"
set "prices[6]=16"

REM Example 1 works
call :SearchInArray "fruits" "Orange"
set /a i=result
echo Result found index: !i!
echo Fruit found: !fruits[%i%]!
echo Price: !prices[%i%]!

echo.

REM Example 2 works
call :SearchInArray "fruits" "Grapes"
set /a i=result
echo Result found index: !i!
echo Fruit found: !fruits[%i%]!
echo Price: !prices[%i%]!

echo.


REM Example 3 using a for loop does not!
set "searchValues=Orange Grapes"
for %%s in (%searchValues%) do (
  call :SearchInArray "fruits" "%%s"
  set /a i=!result!
  echo Result found index: !i!
  echo How to display here the price of the found fruit using the result found index?
)

exit /b

:SearchInArray
set "array=%~1"
set "searchString=%~2"
set "arrayLength=!%array%[0]!"

REM echo array=%array%
REM echo searchString=%searchString%
REM echo arrayLength=%arrayLength%

set "index=-1"
REM Loop through the array elements
for /L %%i in (1, 1, %arrayLength%) do (
  REM echo !%array%[%%i]!
  if "!%array%[%%i]!" == "%searchString%" (
    set "index=%%i"
    goto :ExitLoop
  )
)
:ExitLoop

REM Output the index of the string in the array
REM echo Index of "%searchString%" in the array: %index%
set "result=%index%"
exit /b

Output:

Example 1
Result found index: 3
Fruit found: Orange
Price: 25

Example 2
Result found index: 4
Fruit found: Grapes
Price: 15

Example 3
Result found index: 3
How to display the price of the found fruit using the result found index?
Result found index: 4
How to display the price of the found fruit using the result found index?

In first two examples it works as expected, but if I want to do it in a for loop using an string searchValues containing search strings it does find it but I struggle accessing the prices array using the found index. None works:

  echo Price method 1: prices[!i!]
  echo Price method 2: %prices[!i!]%
  echo Price method 3: !prices[!i!]!
  echo Price method 4: !!prices[!i!]!
  echo Price method 5: %prices[%i%]%
  echo Price method 6: !prices[%i%]!
  echo Price method 7: !!prices[%i%]!

Output:

Price:
Price: i
Price: i
Price: i
Price: 15
Price: 15
Price:
Price: i
Price: i
Price: i
Price: 15
Price: 15

It should be 15 for the first fruit Orange and 25 for the second fruit Grapes.

Jan
  • 2,165
  • 1
  • 18
  • 13
  • You can use this line in your Example 3: `for %%f in (%searchValues%) do for /F "tokens=2 delims=[]" %%i in ('set fruits[ ^| findstr "%%f"') do echo Fruit #%%i found: %%f, Price: !prices[%%i]!` Tested... – Aacini Jun 09 '23 at 02:06
  • ... or this simpler one: `for /F "tokens=2,3 delims=[]=" %%i in ('set fruits[ ^| findstr "%searchValues%"') do echo Fruit #%%i found: %%j, Price: !prices[%%i]!` – Aacini Jun 09 '23 at 06:05
  • @Aacini, was there a particular reason for you to add a basic version of my answer to a comment, especially seven hours later. If, as you've admitted, it is simpler than your other comment, and obviously your own answer, would it not have made more sense to highlight my answer instead? – Compo Jun 09 '23 at 16:36
  • @Compo: Well, your answer is _very different_ in several aspects to my simpler version, but you are right: I should post these comments below your answer, that is the original source of this method... Do you want that I delete these comments and post they below your answer? – Aacini Jun 09 '23 at 18:39
  • TBF @Aacini, the only real difference is that my example was designed to match the exact word whereas yours would match substrings. – Compo Jun 09 '23 at 21:54

4 Answers4

0
REM Example 3
set "searchValues=Orange Grapes"
for %%s in (%searchValues%) do (
  call :SearchInArray "fruits" "%%s"
  set /a i=!result!
  echo Result found index: !i!
  set "cmd=prices[!i!]"
  call echo Price: %%!cmd!%%
  for /F %%A in ('echo %%!cmd!%%') do set "result=%%A"
  echo Result: !result!
)
Jan
  • 2,165
  • 1
  • 18
  • 13
0

The answer to your question is:

call echo Price: %%prices[!i!]%%

... or:

for %%i in (!i!) do echo Price: !prices[%%i]!

... as explained with detail at this answer

However, I like to show you a much simpler method to do the same thing.

Instead of define two arrays (one with fruits and another one with prices), both with numeric indices, it is better to define just one array with prices that have the fruits as indices! In this way, you can directly question if such a fruit exist via if defined price[%fruit%] and also directly get its price! This makes the whole process much simpler:

@echo off
setlocal EnableDelayedExpansion

set "price[Apple]=10"
set "price[Banana]=30"
set "price[Orange]=25"
set "price[Grapes]=15"
set "price[Mango]=12"
set "price[Pineapple]=16"

REM Example 1
set "fruit=Orange"
if defined price[%fruit%] (
   echo Fruit found: %fruit%
   echo Price: !price[%fruit%]!
) else (
   echo Fruit NOT found: %fruit%
)

REM The example 2 is the same as 1

REM Example 3 using a FOR loop
set "searchValues=Orange Grapes"
for %%s in (%searchValues%) do (
   if defined price[%%s] (
      echo Fruit found: %%s
      echo Price: !price[%%s]!
   ) else (
      echo Fruit NOT found: %%s
   )
)

If you want to know which fruits are defined, just do this:

for /F "tokens=2 delims=[]" %%a in ('set price[') do echo %%a

PS - I suggest you to give singular (no plural) names to arrays ("price" and "fruit" instead of prices and fruits)

Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Good suggestion although it only works for 2 arrays (fruits and prices). My original probleem has 3 (linked) arrays. – Jan Jun 09 '23 at 08:33
  • Of course not! This can work with several arrays; the additional array should _also_ have the "basic type" (fruit, in this case) as the index. My point is that if all arrays have numeric indices, you have _first_ to search for the index of the basic type (a fruit), and then use such an index to access the other arrays. With my suggestion you have not to _search_ at all! All array accesses are immediate... – Aacini Jun 09 '23 at 18:31
0

In a very similar manner to Aacini's answer, you can define a structure that contains more information still. The below takes advantage of the for metavariable modifer ~n to parse out the price, and delimits on the = seperator of varname=value to ascertain a quantity

@Echo off

set "$Apple\10=1"
set "$Banana\30=2"
set "$Orange\25=3"
set "$Grapes\15=4"
set "$Mango\12=5"
set "$Pineapple\16=0"

:input
Set /p "item=Choose a fruit: "
2>&1 > nul Set "$%item%" || (
    Echo(Fruit not found
    Goto:input
)

For /f "tokens=1,2 delims==" %%G in ('Set $%Item%')Do Echo(Fruit: %Item% Price:%%~nG Qty:%%H
Echo(Repeat Y/N?
For /f "delims=" %%G in ('Choice /n /c:YN')Do if %%G==Y Goto:option
T3RR0R
  • 2,747
  • 3
  • 10
  • 25
0

Just for the sake of something completely different, and based upon your item values not containing spaces or other potentially problematic characters:

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion

For /F "Delims==" %%G In ('(Set fruits[ ^& Set prices[^) 2^>NUL') Do Set "%%G="

Set "fruits[0]=6"
Set "fruits[1]=Apple"
Set "fruits[2]=Banana"
Set "fruits[3]=Orange"
Set "fruits[4]=Grapes"
Set "fruits[5]=Mango"
Set "fruits[6]=Pineapple"

Set "prices[0]=6"
Set "prices[1]=10"
Set "prices[2]=30"
Set "prices[3]=25"
Set "prices[4]=15"
Set "prices[5]=12"
Set "prices[6]=16"

Set "searchValues=Orange Grapes"

SetLocal EnableDelayedExpansion

For /F "Tokens=2,* Delims=[]=" %%G In ('(Set fruits[^) ^| %SystemRoot%\System32\findstr.exe /RIC:"^fruits\[[123456789][0123456789]*\]=%searchValues: =$" /C:"^fruits\[[123456789][0123456789]*\]=%$"') Do Echo %%H is index %%G and its price is !prices[%%G]!

Pause
EndLocal
Compo
  • 36,585
  • 5
  • 27
  • 39