Array + ArrayFindString/ArrayFindValue.

Статус
В этой теме нельзя размещать новые ответы.
Сообщения
893
Реакции
149
Помог
25 раз(а)
Здравствуйте, у меня возник вопрос по работе ArrayFindString.

У меня есть аррай, я его пушу в нужный момент, и потом получаю его индекс через ArrayFindString. Оно получает нужный индекс, и выводит.
C++:
#include <amxmodx>

new Array: g_ArrayTest;

public plugin_init() {
    g_ArrayTest = ArrayCreate(256);

    register_clcmd("say /array", "CmdArrayPush");
}

public CmdArrayPush(UserId) {
    ArrayPushString(g_ArrayTest, "Yes");
    ArrayPushString(g_ArrayTest, "Yes2");

    new Index = ArrayFindString(g_ArrayTest, "Yes");
    new Index2 = ArrayFindString(g_ArrayTest, "Yes2");

    client_print(UserId, print_chat, "%i", Index2);
    client_print(UserId, print_chat, "%i", Index);
}

Но вопрос, возможно ли работать с этим нативом, если я использую ArrayGetArray/ArrayPushArray, по факту, у меня в этом аррае есть string значения и целые числа.
Возможно ли узнать индекс не пробегаясь цыклом, а найти его по string значению?

Код:
#include <amxmodx>
#include <reapi>

enum any: eArrayData {
    ARRAY_INDEX[128],
    ARRAY_FLAG[16],
    ARRAY_VALUE[256],
    ARRAY_ROUND
};

new const FILEPATH[] = "addons/amxmodx/configs/testitems.ini";

new Array: g_ArrayItems;

public plugin_init() {
    @ReadFile();
}

@ReadFile() {
    new szData[256], iFile, szRound[5], ArrayData[eArrayData];

    iFile = fopen(FILEPATH, "r");

    if(iFile) {
        g_ArrayItems = ArrayCreate(eArrayData);

        while(!feof(iFile)) {
            fgets(iFile, szData, charsmax(szData));
            trim(szData);

            if(!szData[0] || szData[0] == ';')
                continue;

            if(szData[0] == '"') {
                parse(szData,
                    ArrayData[ARRAY_INDEX], charsmax(ArrayData[ARRAY_INDEX]),
                    ArrayData[ARRAY_FLAG], charsmax(ArrayData[ARRAY_FLAG]),
                    ArrayData[ARRAY_VALUE], charsmax(ArrayData[ARRAY_VALUE]),
                    szRound, charsmax(szRound)
                );

                ArrayData[ARRAY_ROUND] = str_to_num(szRound);

                ArrayPushArray(g_ArrayItems, ArrayData);
            }
        }

        fclose(iFile);
    }
}
 
Сообщения
1,304
Реакции
2,303
Помог
57 раз(а)
2023-12-02_08-17-44.jpg
2 Дек 2023
В энумированном дин. массиве можно искать строки при помощи ArrayFindString(), если эти строки являются первым элементом энумерации. В данном случае, это mydata_firstname.
Как видим, "second first name" найдена, а вот 222 или "second second name" уже не находит.
Так же обрати внимание на 4-ый тест. У нас в массиве 5 элементов, т.е. с позиции 0 по 4-ую. Мы ищем "Test" который находится на позиции 4, но ArrayFindString() нашёл его на позиции 3. Потому что ищет он не по полному соответствию строки, а субстрокой. Т.е. "Test" есть в "Test2" и он в массиве на более низкой позиции, его по первому совпадению и отловило. Очень важно понимать этот нюанс и помнить о нём. Организовать при помощи ArrayFindString() своеобразный аналог хранилища по ключу не всегда получится.

Код:
#include amxmodx

enum _:mydata {
    mydata_firstname[32],
    mydata_id,
    mydata_secondname[32]
}

new Array:myArray

public plugin_init() {
    register_srvcmd("test_array", "TestArray")

    myArray = ArrayCreate(mydata)

    new data[mydata]

    data[mydata_firstname] = "first first name"
    data[mydata_id] = 111
    data[mydata_secondname] = "first second name"
    ArrayPushArray(myArray, data)

    data[mydata_firstname] = "second first name"
    data[mydata_id] = 222
    data[mydata_secondname] = "second second name"
    ArrayPushArray(myArray, data)

    data[mydata_firstname] = "third first name"
    data[mydata_id] = 333
    data[mydata_secondname] = "third second name"
    ArrayPushArray(myArray, data)

    data[mydata_firstname] = "Test2"
    data[mydata_id] = 444
    data[mydata_secondname] = "sometest2"
    ArrayPushArray(myArray, data)

    data[mydata_firstname] = "Test"
    data[mydata_id] = 555
    data[mydata_secondname] = "sometest"
    ArrayPushArray(myArray, data)
}

public TestArray() {
    server_print("ArrayFindString() for phrase ^"second first name^", pos: %i", ArrayFindString(myArray, "second first name"))
    server_print("ArrayFindValue() for value 222, pos: %i", ArrayFindValue(myArray, 222))
    server_print("ArrayFindString() for phrase ^"second second name^", pos: %i", ArrayFindString(myArray, "second second name"))
    server_print("ArrayFindString() for word ^"Test^", pos: %i", ArrayFindString(myArray, "Test"))

    return PLUGIN_HANDLED
}
 

Download all Attachments

Последнее редактирование:
Сообщения
678
Реакции
579
Предупреждения
8
Помог
9 раз(а)
BlackSignature, С этим я тоже сталкивался и действительно он так работает. Я использую Trie Array или в паре с Array (тк trie не подходит для рандом и получить все ячейки нельзя) короче зависит от задачи.
 
Сообщения
893
Реакции
149
Помог
25 раз(а)
Всем спасибо за объяснения. Пока тему не закрыли, хочу еще кое-что узнать. Будет ли целесообразно создать несколько трай масивов, и для одного "ключа" записывать нужное значение в нужный трай, или это слишком тупо, и есть идея проще?
В будущем плагин должен работать что-то по типу вип рбс скальпеля, где есть ключ, уловно, health, и для него может быть несколько значений: хп, флаг, что-то по типу такого:

C++:
gifts.ini

; "ключ" "флаг" "значение"
"health" "t" "10"
"health" "d" "50"
Возможно сможет подойти TrieSetArray/TrieGetArray, дабы избавляться от циклов почти в каждом хуке, что бы получить ключ?
 
Сообщения
225
Реакции
90
Помог
1 раз(а)
ImmortalAmxx, я бы массив со значениями хранил в trie, где по флагу выбирал ячейку.
Программирование - работа творческая
 
Сообщения
3,593
Реакции
1,576
Помог
141 раз(а)
тк trie не подходит для рандом и получить все ячейки нельзя
Почему не подходит? TrieSnapshot есть же.
Код:
#include amxmodx

public plugin_init() {
    new Trie:example_trie = TrieCreate();
    TrieSetString(example_trie, "1", "asd");
    TrieSetString(example_trie, "2", "qwe");
    TrieSetString(example_trie, "3", "zxc");
    TrieSetString(example_trie, "4", "qaz");

    new Snapshot:example_snapshot = TrieSnapshotCreate(example_trie);

    new string[8];
    TrieSnapshotGetKey(example_snapshot, random_num(0, 3), string, charsmax(string));

    TrieGetString(example_trie, string, string, charsmax(string));

    log_amx(string)
}
 
Сообщения
893
Реакции
149
Помог
25 раз(а)
Nordic Warrior, а реально ли достать необходимый индекс по какому-то из значений? или только рандомом?
 
Сообщения
893
Реакции
149
Помог
25 раз(а)
Nordic Warrior, понял.

Всем спасибо, кто откликнулся, буду все пробовать. Можно закрывать получается.
 
Статус
В этой теме нельзя размещать новые ответы.

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу