লুয়া স্ট্রিংয়ে স্বতন্ত্র চরিত্রগুলি কীভাবে পুনরাবৃত্তি করা যায়?


93

আমার লুয়ায় একটি স্ট্রিং রয়েছে এবং এটিতে স্বতন্ত্র চরিত্রগুলি পুনরাবৃত্তি করতে চাই। তবে কোনও কোড আমি কাজ করার চেষ্টা করেছি এবং অফিসিয়াল ম্যানুয়ালটিতে কেবল সাবস্ট্রিংগুলি কীভাবে সন্ধান এবং প্রতিস্থাপন করা যায় তা দেখায় :(

str = "abcd"
for char in str do -- error
  print( char )
end

for i = 1, str:len() do
  print( str[ i ] ) -- nil
end

উত্তর:


131

লুয়া ৫.১-এ আপনি কয়েকটি স্ট্রিংয়ের অক্ষরটির পুনরাবৃত্তি করতে পারেন।

মূল লুপটি হ'ল:

আমি = 1, # র জন্য
    স্থানীয় সি = স্টার: সাব (আই, আই)
    - সি দিয়ে কিছু কর
শেষ

তবে string.gmatch()চরিত্রগুলির উপর একটি পুনরাবৃত্তি পেতে একটি প্যাটার্ন ব্যবহার করা আরও দক্ষ হতে পারে :

সি ইন স্ট্রিং এর জন্য: গেম্যাচ " কর
    - সি দিয়ে কিছু কর
শেষ

বা এমনকি string.gsub()প্রতিটি চরের জন্য একটি ফাংশন কল করতে ব্যবহার করতে:

str: gsub ("।", ফাংশন (সি)
    - সি দিয়ে কিছু কর
শেষ)

উপরের stringসমস্তগুলিতে , আমি এই সত্যটি গ্রহণ করেছি যে মডিউলটি সমস্ত স্ট্রিং মানগুলির জন্য একটি মেটাটেবল হিসাবে সেট করা আছে, সুতরাং এর ফাংশনগুলি :স্বরলিপিটি ব্যবহার করে সদস্য হিসাবে ডাকা যেতে পারে । আমি #স্ট্রিংয়ের দৈর্ঘ্য পেতে (5.1, আইআইআরসি থেকে নতুন )ও ব্যবহার করেছি ।

আপনার আবেদনের সর্বোত্তম উত্তরটি অনেকগুলি বিষয়গুলির উপর নির্ভর করে এবং যদি পারফরম্যান্স বিবেচ্য হয় তবে বেঞ্চমার্কগুলি আপনার বন্ধু।

চরিত্রগুলি নিয়ে কেন আপনাকে পুনরাবৃত্তি করতে হবে এবং লুয়ার সাথে আবদ্ধ হয়েছে এমন নিয়মিত এক্সপ্রেশন মডিউলগুলির একটিতে বা রবার্তোর এলপিইজি মডিউলে একটি আধুনিক পদ্ধতির সন্ধানের জন্য যা লুয়ার জন্য পার্সিং এক্সপ্রেশন ব্যাকরণকে কার্যকর করে তা আপনি মূল্যায়ণ করতে পারেন ।


ধন্যবাদ আপনি উল্লেখ করেছেন এলপিইজি মডিউল সম্পর্কে - এটি টোকেনাইজেশনের পরে মূল পাঠ্যে টোকেনের অবস্থানগুলি সংরক্ষণ করে? আমার যে কাজটি সম্পাদন করতে হবে তা হ'ল লুয়ার মাধ্যমে নির্দিষ্ট সরল ভাষা হাইলাইট করা (কোনও সংকলিত সি ++ পার্সার ছাড়াই)। এছাড়াও, এলপিজি ইনস্টল করবেন কীভাবে? মনে হয় এর বিতরণে .c উত্স রয়েছে - এটি কি লুয়ার পাশাপাশি সংকলন করা দরকার?
grigoryvp

বিল্ডিং এলপেইগ একটি ডিএলএল উত্পাদন করবে (বা। তাই) যেখানে সংরক্ষণ করা উচিত সেখানে এটি প্রয়োজন হয়। (যেমন কোথাও আপনার লুয়া ইনস্টলেশনতে বিশ্বব্যাপী প্যাকেজ.পথের সামগ্রী দ্বারা চিহ্নিত।) এছাড়াও আপনি যদি এর সরলিকৃত বাক্য গঠনটি ব্যবহার করতে চান তবে আপনাকে এর সহযোগী মডিউল re.lua ইনস্টল করতে হবে। একটি এলপিজি ব্যাকরণ থেকে, আপনি কলব্যাক পেতে এবং বিভিন্ন উপায়ে পাঠ্য ক্যাপচার করতে পারেন এবং পরবর্তী ব্যবহারের জন্য কেবল মিলের অবস্থানটি সংরক্ষণ করতে ক্যাপচারগুলি ব্যবহার করা অবশ্যই সম্ভব। যদি সিনট্যাক্স হাইলাইটটি লক্ষ্য হয় তবে কোনও পিইজি সরঞ্জামের পছন্দ পছন্দ নয়।
আরবেরটিগ 21

4
সায়টিইটির সর্বশেষ রিলিজের উল্লেখ না করা (২.২২ সাল থেকে) সিন্টিলুয়া অন্তর্ভুক্ত, একটি এলপিজি-ভিত্তিক লেক্সার, যার অর্থ এটি বাক্সের ঠিক বাইরে কাজ করতে পারে, পুনরায় সংকলনের প্রয়োজন নেই।
স্টুয়ার্ট পি। বেন্টলে

11

আপনি যদি লুয়া 5 ব্যবহার করেন তবে চেষ্টা করুন:

for i = 1, string.len(str) do
    print( string.sub(str, i, i) )
end

9

হাতের কাজটির উপর নির্ভর করে এটি ব্যবহার করা সহজ হতে পারে string.byte। এটি দ্রুততম উপায়ও কারণ এটি নতুন নতুন স্ট্রিং তৈরি করা এড়িয়ে যায় যা প্রতিটি নতুন স্ট্রিং হ্যাশ করার জন্য এবং এটি ইতিমধ্যে পরিচিত কিনা তা খতিয়ে দেখার জন্য লুয়ায় বেশ ব্যয়বহুল হতে পারে। আপনি string.byteপঠনযোগ্যতা এবং বহনযোগ্যতা বজায় রাখার জন্য আপনি প্রতীকগুলির কোডের প্রাক-গণনা করতে পারেন ।

local str = "ab/cd/ef"
local target = string.byte("/")
for idx = 1, #str do
   if str:byte(idx) == target then
      print("Target found at:", idx)
   end
end

7

প্রদত্ত উত্তরে ইতিমধ্যে অনেক ভাল পন্থা রয়েছে ( এখানে , এখানে এবং এখানে )। গতি যদি আপনি প্রাথমিকভাবে সন্ধান করেন তবে লুয়ার সিআই এপিআইয়ের মাধ্যমে আপনার কাজটি অবশ্যই করা উচিত, যা কাঁচা লুয়া কোডের চেয়ে বহুগুণ দ্রুত। প্রিলোডেড খণ্ডগুলি (যেমন লোড ফাংশন ) নিয়ে কাজ করার সময়, পার্থক্যটি এত বড় নয়, তবে এখনও যথেষ্ট বিবেচ্য।

খাঁটি লুয়া সমাধানগুলির জন্য , আমি তৈরি করেছি এই ছোট্ট বেঞ্চমার্কটি ভাগ করুন। এটি এই তারিখের প্রতি প্রদত্ত উত্তরকে কভার করে এবং কয়েকটি অপ্টিমাইজেশন যুক্ত করে। তবুও, বিবেচনার জন্য মূল বিষয়টি হ'ল:

স্ট্রিংয়ে অক্ষরগুলি দিয়ে পুনরাবৃত্তি করার জন্য আপনার কতবার দরকার?

  • উত্তরটি যদি একবার "একবার" হয় তবে তার চেয়ে বেশি আপনার ব্যাঙ্কমার্কের প্রথম অংশটি দেখা উচিত ("কাঁচা গতি")।
  • অন্যথায়, দ্বিতীয় অংশটি আরও সুনির্দিষ্ট প্রাক্কলন সরবরাহ করবে, কারণ এটি টেবিলের মধ্যে স্ট্রিংটিকে পার্স করে, যা পুনরাবৃত্তি করা আরও দ্রুত। আপনার পক্ষে এইটির জন্য একটি সাধারণ ক্রিয়া লেখার কথাও বিবেচনা করা উচিত, যেমন @ জারিজ প্রস্তাবিত।

এখানে পূর্ণ কোড:

-- Setup locals
local str = "Hello World!"
local attempts = 5000000
local reuses = 10 -- For the second part of benchmark: Table values are reused 10 times. Change this according to your needs.
local x, c, elapsed, tbl
-- "Localize" funcs to minimize lookup overhead
local stringbyte, stringchar, stringsub, stringgsub, stringgmatch = string.byte, string.char, string.sub, string.gsub, string.gmatch

print("-----------------------")
print("Raw speed:")
print("-----------------------")

-- Version 1 - string.sub in loop
x = os.clock()
for j = 1, attempts do
    for i = 1, #str do
        c = stringsub(str, i)
    end
end
elapsed = os.clock() - x
print(string.format("V1: elapsed time: %.3f", elapsed))

-- Version 2 - string.gmatch loop
x = os.clock()
for j = 1, attempts do
    for c in stringgmatch(str, ".") do end
end
elapsed = os.clock() - x
print(string.format("V2: elapsed time: %.3f", elapsed))

-- Version 3 - string.gsub callback
x = os.clock()
for j = 1, attempts do
    stringgsub(str, ".", function(c) end)
end
elapsed = os.clock() - x
print(string.format("V3: elapsed time: %.3f", elapsed))

-- For version 4
local str2table = function(str)
    local ret = {}
    for i = 1, #str do
        ret[i] = stringsub(str, i) -- Note: This is a lot faster than using table.insert
    end
    return ret
end

-- Version 4 - function str2table
x = os.clock()
for j = 1, attempts do
    tbl = str2table(str)
    for i = 1, #tbl do -- Note: This type of loop is a lot faster than "pairs" loop.
        c = tbl[i]
    end
end
elapsed = os.clock() - x
print(string.format("V4: elapsed time: %.3f", elapsed))

-- Version 5 - string.byte
x = os.clock()
for j = 1, attempts do
    tbl = {stringbyte(str, 1, #str)} -- Note: This is about 15% faster than calling string.byte for every character.
    for i = 1, #tbl do
        c = tbl[i] -- Note: produces char codes instead of chars.
    end
end
elapsed = os.clock() - x
print(string.format("V5: elapsed time: %.3f", elapsed))

-- Version 5b - string.byte + conversion back to chars
x = os.clock()
for j = 1, attempts do
    tbl = {stringbyte(str, 1, #str)} -- Note: This is about 15% faster than calling string.byte for every character.
    for i = 1, #tbl do
        c = stringchar(tbl[i])
    end
end
elapsed = os.clock() - x
print(string.format("V5b: elapsed time: %.3f", elapsed))

print("-----------------------")
print("Creating cache table ("..reuses.." reuses):")
print("-----------------------")

-- Version 1 - string.sub in loop
x = os.clock()
for k = 1, attempts do
    tbl = {}
    for i = 1, #str do
        tbl[i] = stringsub(str, i) -- Note: This is a lot faster than using table.insert
    end
    for j = 1, reuses do
        for i = 1, #tbl do
            c = tbl[i]
        end
    end
end
elapsed = os.clock() - x
print(string.format("V1: elapsed time: %.3f", elapsed))

-- Version 2 - string.gmatch loop
x = os.clock()
for k = 1, attempts do
    tbl = {}
    local tblc = 1 -- Note: This is faster than table.insert
    for c in stringgmatch(str, ".") do
        tbl[tblc] = c
        tblc = tblc + 1
    end
    for j = 1, reuses do
        for i = 1, #tbl do
            c = tbl[i]
        end
    end
end
elapsed = os.clock() - x
print(string.format("V2: elapsed time: %.3f", elapsed))

-- Version 3 - string.gsub callback
x = os.clock()
for k = 1, attempts do
    tbl = {}
    local tblc = 1 -- Note: This is faster than table.insert
    stringgsub(str, ".", function(c)
        tbl[tblc] = c
        tblc = tblc + 1
    end)
    for j = 1, reuses do
        for i = 1, #tbl do
            c = tbl[i]
        end
    end
end
elapsed = os.clock() - x
print(string.format("V3: elapsed time: %.3f", elapsed))

-- Version 4 - str2table func before loop
x = os.clock()
for k = 1, attempts do
    tbl = str2table(str)
    for j = 1, reuses do
        for i = 1, #tbl do -- Note: This type of loop is a lot faster than "pairs" loop.
            c = tbl[i]
        end
    end
end
elapsed = os.clock() - x
print(string.format("V4: elapsed time: %.3f", elapsed))

-- Version 5 - string.byte to create table
x = os.clock()
for k = 1, attempts do
    tbl = {stringbyte(str,1,#str)}
    for j = 1, reuses do
        for i = 1, #tbl do
            c = tbl[i]
        end
    end
end
elapsed = os.clock() - x
print(string.format("V5: elapsed time: %.3f", elapsed))

-- Version 5b - string.byte to create table + string.char loop to convert bytes to chars
x = os.clock()
for k = 1, attempts do
    tbl = {stringbyte(str, 1, #str)}
    for i = 1, #tbl do
        tbl[i] = stringchar(tbl[i])
    end
    for j = 1, reuses do
        for i = 1, #tbl do
            c = tbl[i]
        end
    end
end
elapsed = os.clock() - x
print(string.format("V5b: elapsed time: %.3f", elapsed))

উদাহরণ আউটপুট (লুয়া 5.3.4, উইন্ডোজ) :

-----------------------
Raw speed:
-----------------------
V1: elapsed time: 3.713
V2: elapsed time: 5.089
V3: elapsed time: 5.222
V4: elapsed time: 4.066
V5: elapsed time: 2.627
V5b: elapsed time: 3.627
-----------------------
Creating cache table (10 reuses):
-----------------------
V1: elapsed time: 20.381
V2: elapsed time: 23.913
V3: elapsed time: 25.221
V4: elapsed time: 20.551
V5: elapsed time: 13.473
V5b: elapsed time: 18.046

ফলাফল:

আমার ক্ষেত্রে, string.byteএবং string.subকাঁচা গতির দিক থেকে দ্রুততম ছিল। ক্যাশে টেবিল ব্যবহার করার সময় এবং প্রতি লুপে 10 বার এটি পুনরায় ব্যবহার করার সময়,string.byte চারকোডগুলি চরগুলিতে ফিরে রূপান্তর করার সময়ও সংস্করণটি দ্রুত ছিল (যা সর্বদা প্রয়োজনীয় নয় এবং ব্যবহারের উপর নির্ভর করে)।

আপনি সম্ভবত লক্ষ্য করেছেন, আমি আমার পূর্ববর্তী মানদণ্ডের উপর ভিত্তি করে কিছু অনুমান করেছি এবং সেগুলি কোডে প্রয়োগ করেছি:

  1. লুপের অভ্যন্তরে ব্যবহৃত হলে লাইব্রেরির ফাংশনগুলি সর্বদা স্থানীয় করা উচিত, কারণ এটি অনেক দ্রুত।
  2. লুয়া টেবিলের মধ্যে নতুন উপাদান সন্নিবেশ করা এর tbl[idx] = valueচেয়ে বেশি দ্রুত table.insert(tbl, value)
  3. টেবিল ব্যবহার করে লুপিং এর for i = 1, #tblচেয়ে কিছুটা দ্রুতfor k, v in pairs(tbl)
  4. সর্বদা কম ফাংশন কল সহ সংস্করণ পছন্দ করুন, কারণ কলটি নিজেই সম্পাদনের সময়টিতে কিছুটা যুক্ত করে।

আশা করি এটা সাহায্য করবে.


0

সমস্ত লোক কম অনুকূল পদ্ধতির পরামর্শ দেয়

সেরা হবে:

    function chars(str)
        strc = {}
        for i = 1, #str do
            table.insert(strc, string.sub(str, i, i))
        end
        return strc
    end

    str = "Hello world!"
    char = chars(str)
    print("Char 2: "..char[2]) -- prints the char 'e'
    print("-------------------\n")
    for i = 1, #str do -- testing printing all the chars
        if (char[i] == " ") then
            print("Char "..i..": [[space]]")
        else
            print("Char "..i..": "..char[i])
        end
    end

কোন কাজের জন্য "কম অনুকূল"? কোন কাজের জন্য "সেরা"?
ওলেগ ভি। ভলকভ

0

একটি স্ট্রিং তৈরি করতে আইট্রেটিং এবং এই স্ট্রিংটিকে লোড () সহ একটি টেবিল হিসাবে ফিরিয়ে আনছে ...

itab=function(char)
local result
for i=1,#char do
 if i==1 then
  result=string.format('%s','{')
 end
result=result..string.format('\'%s\'',char:sub(i,i))
 if i~=#char then
  result=result..string.format('%s',',')
 end
 if i==#char then
  result=result..string.format('%s','}')
 end
end
 return load('return '..result)()
end

dump=function(dump)
for key,value in pairs(dump) do
 io.write(string.format("%s=%s=%s\n",key,type(value),value))
end
end

res=itab('KOYAANISQATSI')

dump(res)

রাখা...

1=string=K
2=string=O
3=string=Y
4=string=A
5=string=A
6=string=N
7=string=I
8=string=S
9=string=Q
10=string=A
11=string=T
12=string=S
13=string=I
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.