2010-10-28 6 views
0

Я новый программист и начал с lua. я хочу сделать функцию этого массива в -b, следующие моя программа, она не работает хорошоВ lua, как выполнять функцию a-b, когда a & b являются массивами или таблицами

function delTwo (a ,b) 
local i = 0 
    local lengthA = #a 
    local lengthB = #b 


    for i = 1 ,lengthA do 
    for j =1 , lengthB do 
    if a[i]==b[j] then 
    a[i] = nil 
    end 
    end 

    for i = 1 , lengthA do 
    if a[i]~= nil then 
    retrun a[i] 
    end 
    end 
    end 

    end 

a = {10, 20, 30} 
b={11,20,122} 
for element in delTwo (a ,b) do 
    print(element) 
end 

У меня есть два вопроса, первый вход: 16: «=» ожидается около «а ' Retrun в [I] Y должен я изменился в Retrun = а [я] и какова разница между ними

второй вход: 3: попытка получить длину местного „а“ (в нулевой стоимости) что случилось с этим, даже если я был изменен на локальную длину A = table.getn (a) будет введен: 3: неверный аргумент # 1 в 'getn' (таблица ожидаемая, полученная ноль)

+1

Я не знаю, очень хорошо, но относительно вашей первой ошибки: действительно ли ваш код говорит «retrun a [i]'? Если это так, то я предполагаю, что вы хотели набрать 'return'. Интерпретатор lua предполагает, что 'retrun' - это локальная переменная, так как не распознает его как допустимое ключевое слово, поэтому ожидает инициализации задания. – eldarerathis

+0

спасибо, u решить мою первую проблему, я все еще работаю со вторым – workfor3days

+1

Я не понимаю, каков ожидаемый результат delTwo. Можете ли вы написать ожидаемый результат своей программы? – kikito

ответ

2

Первая проблема уже была решена, но в отношении второго это означает, что a в какой-то момент выполнения вашей программы nil (== null). Однако я не смог повторить это с вашим примером.

Я не совсем уверен, чего вы пытаетесь достичь, но я рекомендую сначала создать функцию, которая создает новую таблицу, которая сохранит желаемый результат, а затем повторите ее, используя pairs (или обычный цикл). Что-то вроде следующего:

function delTwo(a, b) 
    local result = {} 
    --# Logic here. 
    --# Use result[#result + 1] = ... to insert values. 
    return result 
end 

for k, v in pairs(delTwo(a,b)) do print(k, v) end 
+0

У меня все еще есть вопрос, если у меня есть такая программа, как – workfor3days

+0

Функция a (t) local i = 0 local n = table.getn (t) --local s = table.getn (s) return function() i = i + 1 если i <= n, то вернуть t [i] конец - для i = n + 1, n + s do return s [in] end end конец т = {10, 20, 30} для элемента в (T) делают печатей (элемент) конца , который будет правильно – workfor3days

+0

но если я изменить в функцию а (t, s) локальных i = 0 local n = table.getn (t) local s = table.getn (s) return function() i = i + 1 если i <= n, то верните t [i] end - при г = N + 1, N + S сделать возвращение ей [в] конце конец конечного Т = {10, 20, 30} для элемента в (T) делают печатей (элемент) end Неправильно Y Функция a (y, t) не может работать? – workfor3days

2

Прежде всего, ваш отступы маскировать проблему с баланса между for с и end с.

Что у вас есть:

function delTwo (a ,b) 
    local i = 0 
    local lengthA = #a 
    local lengthB = #b 

    for i = 1, lengthA do 

    for j = 1, lengthB do 
     if a[i] == b[j] then 
     a[i] = nil 
     end 
    end 

    for i = 1, lengthA do --// Iterating i while iterating i. Bad things happen! 
     if a[i] ~= nil then 
     return a[i] 
     end 
    end 

    end 

end 

Кроме того, поскольку вы изменяете a внутри цикла, его длина становится меньше, и вы будете в конечном итоге к нему доступ с недопустимым индексом.


Тогда как вы использовать возвращаемое значение delTwo «s.

Вот объяснение того, как итераторы работают в Lua: http://lua-users.org/wiki/IteratorsTutorial

Когда вы пишете что-то вроде for i in <expr>, <expr> должен вернуть три значения: функцию итератор, состояние объекта, и начальное значение.

Каждая итерация, функция итератора будет вызываться с объектом состояния и текущим значением (начиная с начального значения в <expr>). Если она возвращает nil, итерация останавливается, в противном случае возвращаемых значений назначена ваш переменный цикл, тело цикла for выполняется, и функция итератора будет вызываться снова с тем же состоянием объектом и новой текущими значение, которое является первым из ваших переменных цикла (i в этом случае).

A (относительно) простой пример может помочь вам понять:

local state = {} 
state["toggle"] = true 

function iterator_func(state, prev_i) 
    --// Calculate current value based on previous value 
    i = prev_i + 1 

    --// Stop iteration if we've had enough 
    if i > 10 then 
     return nil 
    end 

    local msg 
    if state["toggle"] then 
     msg = "It's on!" 
     state["toggle"] = false 
    else 
     msg = "It's off!" 
     state["toggle"] = true 
    end 

    return i, i*2, i*3, msg 
end 

--// Notice the initial value is 0, the value *before* our first iteration 
for i, double, triple, msg in iterator_func, state, 0 do 
    print(tostring(i)..", " 
      ..tostring(double)..", " 
      ..tostring(triple)..", " 
      ..tostring(msg)) 
end 

--// Prints: 
--// 1, 2, 3, It's on! 
--// 2, 4, 6, It's off! 
--// ... 
--// 10, 20, 30, It's off! 

Lua поставляется с функциями генератора два итератора: ipairs и pairs. Они берут таблицу и возвращают то, что необходимо для цикла for, чтобы перебрать над значениями, хранящимися в этой таблице.

ipairs ожидает, что таблица с цифровыми клавишами от 1 до #table и генерирует итератор, который будет итерацию по тем индексам в порядке, возвращаясь каждый раз, когда индекс и значения:

for i, v in ipairs({ 10, 20, 30 }) do 
    print("["..i.."] = " .. v) 
end 
--// Prints: 
--// [1] = 10 
--// [2] = 20 
--// [3] = 30 

pairs принимает любой вид таблицы и генерирует итератор, который возвращает пары ключ и значение, причем пары поступают в любом порядке. В этом случае ключи могут быть любыми, кроме nil, даже таблиц!

aKey = {} 
t = { ["First"] = 10, [2.0] = 20, [aKey] = 30 } 

for k, v in pairs(t) do 
    print("["..tostring(k).."] = " .. tostring(v)) 
end 
--// Prints something like: 
--// [table: 0x95860b0] = 30 
--// [First] = 10 
--// [2] = 20 

Итак, у вас есть два подхода.

Если вы хотите delTwo вернуть таблицу, вы должны написать свой for цикл, как это:

for idx, element in ipairs(delTwo(a, b)) do 
    print(element) 
end  
--// delTwo *must* return a table with correct numeric indices 

или как это:

for _, element in pairs(delTwo(a, b)) do 
    print(element) 
end 
--// Conventionally, you use _ as a variable name if you plan to just ignore it. 

Вот кое-что для вас учиться. Это большой кусок кода, но я надеюсь, вы сможете это понять и узнать что-то от него.

--////////////////////////////////////////////////////////////////////////// 
--// 
--// APPROACH #1 
--// 

--// 
--// This function modifies table a in place, 
--// removing elements that are also found in b 
--// 
local function delTwo_1(a, b) 
    local lengthB = #b 

    --// a's length may change if we remove an element from it, 
    --// so iterate over b and recalculate a's length every iteration. 
    for j = 1, lengthB do 
     local lengthA = #a 
     for i = 1, lengthA do  
      if a[i] == b[j] then 
       table.remove(a, i) 

       --// Don't use " a[i] = nil ". 
       --// This will just leave you with a nil element in the "middle" 
       --// of the table, and as it happens ipairs() stops 
       --// at the first nil index it finds. 

       --// So: 
       --// a = { [1] = 10, [2] = 20, [3] = 30} 
       --// a[2] = nil 
       --// -- a is now { [1] = 10, [2] = nil, [3] = 30 }. 
       --// 
       --// -- ipairs(a) will now return (1, 10) and then stop. 
       --// 
       --// -- pairs(a) will return both (1, 10) and (3, 30) 
      end 
     end 
    end 

    --// Return table a if you want,but it's been modified "outside" as well 
    return a 
end 

--////////////////////////////////////////////////////////////////////////// 
--// 
--// APPROACH #2 
--// 

--// 
--// This function calculates the difference between two tables, 
--// without modifying any of them. 
--// It will be used in our iterator generator. 
--// 
local function tableDiff(a, b) 
    local res = {} 

    for i = 1, #a do 
     local skip = false 

     for j = 1, #b do 
      if a[i] == b[j] then 
       skip = true 
       break 
      end 
     end 

     if not skip then 
      res[#res+1] = a[i] 
     end 
    end 

    return res 
end 

--// 
--// This function is an iterator generator. 
--// It returns an iterator function, a state object and an initial value 
--// 
local function delTwo_2(a, b) 

    --// Some preliminary calculations... 
    local res = tableDiff(a, b) 

    --// We don't really need state in this case, because we could 
    --// refer directly to our res variable inside our iterator function, 
    --// but this is just for demonstration purposes. 
    local state = {} 
    state["result"] = res 

    local function iterator(state, key) 
     local result = state["result"] 

     --// Our key is a numeric index, incremented every iteration 
     --// before anything else (that's just how it works) 
     key = key + 1 

     if key > #result then 
      --// If key is greater than our table length, 
      --// then we already iterated over all elements. 
      --// Return nil to terminate. 
      return nil 
     end 

     local element = result[key] 

     --// Just because we can... 
     local msg = "We're at element "..key 

     return key, element, msg 
    end 


    local initialKey = 0 --// We start "before" index 1 

    return iterator, state, initialKey 
end 




do 
    --// TESTS 

    do 
     --// TESTING APPROACH #1 

     a = {10, 20, 30} 
     b = {11, 20, 122} 

     print "******************* delTwo_1 *******************" 
     print "Here's delTwo_1's result:" 

     --// Table a is modified in place 
     delTwo_1(a, b) 
     for i, element in ipairs(a) do 
      print("["..i.."] = "..tostring(element)) 
     end 

     print() 
     print "Here's a after delTwo_1:" 
     for i, element in ipairs(a) do 
      print("["..i.."] = "..tostring(element)) 
     end 
    end 

    print() 
    print() 

    do 
     --// TESTING APPROACH #2 
     a = {10, 20, 30} 
     b = {11, 20, 122} 

     print "******************* delTwo_2 *******************" 
     print "Here's delTwo_2's result:" 
     --// Notice how this compares to what 
     --// is returned by our iterator function 
     for idx, element, msg in delTwo_2(a, b) do 
      print(tostring(element) .. "  (Msg: "..msg..")") 
     end 

     print() 
     print "Here's a after delTwo_2:" 
     for i, element in ipairs(a) do 
      print("["..i.."] = "..tostring(element)) 
     end 
    end 
end 

Этот пост является свидетельством того, сколько свободного времени у меня в руках :)

+0

Спасибо, что за то, что набрал все это, я снова его прочитаю и снова. – workfor3days

+0

+1 для усилий в одиночку, но вы заслуживаете +2 за очень информативный ответ. – ponzao

1

Альтернативный вариант, который использует метатаблицы

local mt = { --// Just creates a metatable base 
__sub = function (a, b) --// Function is the same as Zecc just formatted differently 
    local lengthB = #b 
    for j = 1, lengthB do 
     local lengthA = #a 
     for i = 1, lengthA do 
      if a[i] == b[j] then table.remove(a, i) end 
     end 
    end 
    return a 
end 
} 

a = {10, 20, 30} --// Same arrays 
b = {11, 20, 122} 

setmetatable(a, mt) -- //Use this to give the arrays the __sub function 
setmetatable(b, mt) 

c = a - b --// Then you can use the maths operator on it 

for k, v in ipairs(c) do --// printing them out gives the same as above 
    print(k, v) 
end 

Затем, если вы хотите использовать различные массивы таким же образом, просто используйте setmetatable(x, mt), где x - таблица, в которой вы хотите иметь функцию, и она должна работать.

0

Ниже моя реализация вашей функции, которая выполняет следующие действия: 1. вычесть из элемента х в А, элемент у из В (если у существует)

function arrDel(a,b) 
     local result = {} 
     for i = 1, #a, 1 do 
      result[i] = a[i] - (b[i] or 0) -- 'or 0' exists to cope with if #b < #a 
     end 
     return result 
end 

Этот код создает и заполняет таблицу с именем результат, который является «результатом» вычитания b из a. В lua существует два типа цикла for: числовое и общее. Цикл в вышеуказанной функции использует числовой тип цикла. Этот цикл следует использовать либо в том случае, когда блок кода, который он содержит, должен выполняться известным числом раз, либо индексирование, чтобы найти значение, которое использует цикл, тривиально.

sytanx выглядит следующим образом:

for counter = initial, final, increment do 
    body 
end 

Приращение является необязательным, по умолчанию это 1.


Для демонстрации другого типа петли этой небольшой функции печатает очень просто таблица:

function tprint(t) 
    local res = {} 
    for _,v in ipairs(t) do 
     res[#res+1] = v 
    end 
    print("{"..table.concat(res,",").."}") 
end 

Здесь используется общее значение (используется ключевое слово 'in'). Общий способ позволяет легко обходить сложные объекты. Например, скажем, что объект содержит записи пользователей, однако записи были сохранены в разделах i.e VIP, Administrator, Guest и т. Д. И вы хотели обойти ВСЕ пользователей. Вы можете написать функцию, которая затем используется в родовом для делать это легко с выражением, подобным этому:

for user in object.traverseUsers() do 
    body 
end 

Реализация таких итераторов выходит за рамки ответа на этот вопрос, но большая пояснения можно найти здесь Generic For (PIL)

0
  1. Вы пишете "return" как "retrun".
  2. Если есть такая возможность, что-то другое, чем за столом будет дано, но вы все еще хотите, чтобы сохранить код работает, используйте этот

    local lengthA = a and #a or 0 
    local lengthB = b and #b or 0 
    
  3. Не действительно необходимо, но только немного информации; Нет необходимости говорить о том

    if a[i] ~= nil then 
    

Вы не можете просто сделать это вместо:

if a then 
1

Проблема заключается в том, как установить разницу, следующая функция подготовки Dict возможных значений, чтобы удалить из массива Ь , и проверьте, содержит ли массив a его при перемещении. Функция имеет необязательный флаг inplace, если изменение делает вместо массива a или возвращает новый.

function arrayDiff(a,b,inplace) 
    inplace = inplace~=false -- default inplace 
    local ret = inplace and a or {} 
    local toRemove = {} -- a dict for value to remove 
    for i=1,#b do toRemove[b[i]]=true end 
    local nxtInsert = 0 
    local aLen = #a 
    for i=1,aLen do 
    local value = a[i] 
    if not toRemove[value] then 
     nxtInsert = nxtInsert + 1 
     ret[nxtInsert] = value 
    end  
    end 
    if inplace then 
    for i=nxtInsert+1,aLen do ret[i]=nil end 
    end 
    return ret 
end 
Смежные вопросы