মোড়িত ধ্রুবক সময়ে আর এর তালিকায় কোনও বস্তু যুক্ত করুন, হে (1)?


245

আমার যদি কিছু আর তালিকা mylistথাকে তবে objআপনি এটিতে একটি আইটেম যুক্ত করতে পারেন:

mylist[[length(mylist)+1]] <- obj

তবে অবশ্যই আরও কিছু কমপ্যাক্ট উপায় আছে। আমি যখন আর এ নতুন ছিলাম, তখন আমি এ জাতীয় লেখার চেষ্টা lappend()করেছি:

lappend <- function(lst, obj) {
    lst[[length(lst)+1]] <- obj
    return(lst)
}

তবে অবশ্যই এটি আর এর কল-বাই-নাম শব্দার্থবিজ্ঞানের কারণে কাজ করে না ( lstকল করার পরে কার্যকরভাবে অনুলিপি করা হয়, তাই পরিবর্তনের ক্ষেত্রের lstবাইরে দৃশ্যমান হয় না lappend()I আমি জানি আপনি কোনও আর ফাংশনে পরিবেশের হ্যাকিং করতে পারবেন বাইরের বাইরে পৌঁছাতে you আপনার ফাংশন এবং কলিং পরিবেশ পরিবর্তন করতে সুযোগ, কিন্তু এটি একটি সহজ হাততালি ফাংশন লিখতে একটি বড় হাতুড়ি মত মনে হয়।

কেউ কি আরও সুন্দর উপায় এটি করার পরামর্শ দিতে পারে? বোনাস পয়েন্ট যদি এটি উভয় ভেক্টর এবং তালিকার জন্য কাজ করে।


5
আর এর অপরিবর্তনীয় ডেটা বৈশিষ্ট্য রয়েছে যা প্রায়শই কার্যকরী ভাষায় পাওয়া যায়, এটি বলতে ঘৃণা করা হয়, তবে আমি মনে করি আপনাকে কেবল এটির মোকাবেলা করতে হবে। এটির উপকারিতা এবং এর বিপরীতে রয়েছে
ড্যান

আপনি যখন "কল-বাই-নাম" বলছেন তখন আপনি সত্যিকার অর্থে "কল-বাই-ভ্যালু" মানে, তাই না?
কেন উইলিয়ামস

7
না, এটি অবশ্যই কল-বাই-মান নয়, অন্যথায় এটি কোনও সমস্যা হবে না। আর প্রকৃতপক্ষে কল-বাই-প্রয়োজন ব্যবহার করে ( এন.ইউইকিপিডিয়া . org / উইকি / মূল্যায়ন_আরস্তাদ্বা # কল_বাই_নিড )।
নিক

4
আপনার ভেক্টর / তালিকার প্রাক-বরাদ্দ করা ভাল ধারণা: এন = 100 মাইলিস্ট = ভেক্টর ('তালিকা', এন) এর জন্য (আমি 1: এন) {# মাইলিস্ট [[i]] = ... growing বাড়ানো থেকে বিরত থাকুন 'আর।
ফার্নান্দো

দুর্ঘটনাক্রমে আমি উত্তরটি এখানে পেয়েছি, stackoverflow.com/questions/17046336/… এত সহজ অ্যালগরিদম বাস্তবায়ন করা এত কঠিন!
কেএইচ কিম

উত্তর:


255

যদি এটি স্ট্রিংয়ের একটি তালিকা থাকে তবে কেবলমাত্র c()ফাংশনটি ব্যবহার করুন :

R> LL <- list(a="tom", b="dick")
R> c(LL, c="harry")
$a
[1] "tom"

$b
[1] "dick"

$c
[1] "harry"

R> class(LL)
[1] "list"
R> 

এটি ভেক্টরগুলিতেও কাজ করে, তাই আমি কী বোনাস পয়েন্ট পাব?

সম্পাদনা (2015-ফেব্রুয়ারি -01): এই পোস্টটি তার পঞ্চম জন্মদিনে প্রকাশিত হচ্ছে। কিছু দয়ালু পাঠকরা এর সাথে যে কোনও ত্রুটিগুলি পুনরাবৃত্তি করে চলেছেন, তাই সমস্ত উপায়ে নীচের কিছু মন্তব্য দেখুন। listপ্রকারের জন্য একটি পরামর্শ :

newlist <- list(oldlist, list(someobj))

সাধারণভাবে, আর প্রকারগুলি সমস্ত ধরণের এবং ব্যবহারের জন্য একটি এবং কেবল একটি আইডিয়মকে শক্ত করে তুলতে পারে।


19
এটি সংযোজন করে না ... এটি সম্মতি দেয়। বলা LLহওয়ার পরেও দুটি উপাদান থাকবে C(LL, c="harry")
নিক

27
শুধু কলিজা থেকে reassign: LL <- c(LL, c="harry")
ডার্ক এডেলবুয়েটেল

51
এটি কেবল স্ট্রিংয়ের সাথে কাজ করে। যদি ক, খ এবং সি পূর্ণসংখ্যা ভেক্টর হয় তবে আচরণটি সম্পূর্ণ আলাদা।
আলেকজান্দ্রে র‌্যাডমেকার

8
@ ডার্ক: আপনার চেয়ে পেরেনরা আমার চেয়ে আলাদাভাবে বাসা বেঁধেছে। আমার কলে c()2 আর্গুমেন্ট নেই: LIST আমি সংযোজন করার চেষ্টা করছি যথা list(a=3, b=c(4, 5)), এবং আইটেমের আমি সংযোজন করতে চেষ্টা করছি, যথা c=c(6, 7)। আপনি যদি আমার পদ্ধতির ব্যবহার করেন তবে আপনি দেখতে পাবেন যে 2 টি তালিকার আইটেমগুলি সংযুক্ত করা হয়েছে ( 6এবং 7নাম সহ c1এবং নামগুলি c2) পরিবর্তে একটি একক 2-উপাদান ভেক্টরের নামটি cস্পষ্টভাবে উদ্দেশ্যযুক্ত!
j_random_hacker

7
তাহলে কি উপসংহার mylist <- list(mylist, list(obj))? যদি হ্যাঁ তবে উত্তরটি সংশোধন করে ভাল লাগবে
ম্যাথু

96

ওপি (এপ্রিল ২০১২ এ প্রশ্নের আপডেটের পুনর্বিবেচনায়) মোড়বিহীন ধ্রুবক সময়ের তালিকায় কোনও তালিকা যুক্ত করার উপায় আছে কিনা তা জানতে আগ্রহী, উদাহরণস্বরূপ, সি ++ vector<>ধারক সহ কিছু করা যেতে পারে । এখানে সর্বোত্তম উত্তর (গুলি?) এখন পর্যন্ত কেবলমাত্র একটি নির্দিষ্ট আকারের সমস্যা প্রদত্ত বিভিন্ন সমাধানের জন্য আপেক্ষিক সম্পাদনের সময়গুলি দেখায়, তবে বিভিন্ন সমাধানের অ্যালগরিদমিক দক্ষতার কোনওটিকেই সরাসরি সম্বোধন করবেন না। উত্তরের অনেকের নীচের মন্তব্যগুলি কয়েকটি সমাধানের অ্যালগরিদমিক দক্ষতা নিয়ে আলোচনা করে তবে আজ পর্যন্ত প্রতিটি ক্ষেত্রে (এপ্রিল 2015-এ) তারা ভুল সিদ্ধান্তে পৌঁছেছে।

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

  • ধ্রুবক বা ও (1) বৃদ্ধি:

    যদি কোনও প্রদত্ত কার্য সম্পাদন করার জন্য প্রয়োজনীয় সময়টি সমস্যার আকার দ্বিগুণের সাথে একই থাকে , তবে আমরা বলি অ্যালগরিদম ধ্রুবক সময় বৃদ্ধি বা "বিগ ও" নোটেশনে বর্ণিত, ও (1) সময়ের বৃদ্ধি প্রদর্শন করে। যখন ওপি ধীরে ধীরে সময় "amorised" বলে, তার সহজ অর্থ "দীর্ঘমেয়াদে" ... অর্থাত্ যদি কোনও একক ক্রিয়াকলাপটি মাঝে মাঝে স্বাভাবিকের চেয়ে অনেক বেশি সময় নেয় তবে (উদাহরণস্বরূপ যদি পূর্বনির্ধারিত বাফারটি শেষ হয়ে যায় এবং মাঝে মাঝে বৃহত্তর আকার পরিবর্তন করতে হয়) বাফারের আকার), যতক্ষণ দীর্ঘমেয়াদী গড় পারফরম্যান্স স্থির সময় হিসাবে থাকে, তবুও আমরা এটিকে ও (1) বলব।

    তুলনার জন্য, আমি "লিনিয়ার সময়" এবং "চতুর্ভুজ সময়" বর্ণনা করব:

  • লিনিয়ার বা ও (এন) বৃদ্ধি:

    যদি কোনও প্রদত্ত টাস্ক সম্পাদনের জন্য প্রয়োজনীয় সময় দ্বিগুণ হয়ে যায় সমস্যার আকার দ্বিগুণ হয়ে যায় , তবে আমরা বলি অ্যালগরিদম রৈখিক সময় বা ও (এন) এর বৃদ্ধি প্রদর্শন করে।

  • চতুষ্কোণ বা O (n 2 ) বৃদ্ধি:

    যদি কোনও প্রদত্ত কার্য সম্পাদন করার জন্য প্রয়োজনীয় সময় সমস্যার আকারের বর্গক্ষেত্র বৃদ্ধি পায় , তবে আমরা তাদের বলি যে অ্যালগোরিদমটি চতুর্ভুজ সময় বা ও (এন 2 ) বৃদ্ধি প্রদর্শন করে।

অ্যালগরিদমের আরও অনেক দক্ষতা শ্রেণি রয়েছে; আমি আরও আলোচনার জন্য উইকিপিডিয়া নিবন্ধটি স্থগিত করি ।

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

library(microbenchmark)
### Using environment as a container
lPtrAppend <- function(lstptr, lab, obj) {lstptr[[deparse(substitute(lab))]] <- obj}
### Store list inside new environment
envAppendList <- function(lstptr, obj) {lstptr$list[[length(lstptr$list)+1]] <- obj} 
runBenchmark <- function(n) {
    microbenchmark(times = 5,  
        env_with_list_ = {
            listptr <- new.env(parent=globalenv())
            listptr$list <- NULL
            for(i in 1:n) {envAppendList(listptr, i)}
            listptr$list
        },
        c_ = {
            a <- list(0)
            for(i in 1:n) {a = c(a, list(i))}
        },
        list_ = {
            a <- list(0)
            for(i in 1:n) {a <- list(a, list(i))}
        },
        by_index = {
            a <- list(0)
            for(i in 1:n) {a[length(a) + 1] <- i}
            a
        },
        append_ = { 
            a <- list(0)    
            for(i in 1:n) {a <- append(a, i)} 
            a
        },
        env_as_container_ = {
            listptr <- new.env(parent=globalenv())
            for(i in 1:n) {lPtrAppend(listptr, i, i)} 
            listptr
        }   
    )
}

@ ক্রোন অ্যাক্রোনিস দ্বারা পোস্ট করা ফলাফলগুলি অবশ্যই মনে করে যে a <- list(a, list(i))পদ্ধতিটি দ্রুততম, কমপক্ষে কমপক্ষে 10000 সমস্যার আকারের জন্য, তবে একক সমস্যার আকারের ফলাফলগুলি সমাধানটির বৃদ্ধিকে চিহ্নিত করে না। তার জন্য, আমাদের বিবিধ সমস্যার আকারের সাথে ন্যূনতম দুটি প্রোফাইলিং পরীক্ষা চালানো দরকার:

> runBenchmark(2e+3)
Unit: microseconds
              expr       min        lq      mean    median       uq       max neval
    env_with_list_  8712.146  9138.250 10185.533 10257.678 10761.33 12058.264     5
                c_ 13407.657 13413.739 13620.976 13605.696 13790.05 13887.738     5
             list_   854.110   913.407  1064.463   914.167  1301.50  1339.132     5
          by_index 11656.866 11705.140 12182.104 11997.446 12741.70 12809.363     5
           append_ 15986.712 16817.635 17409.391 17458.502 17480.55 19303.560     5
 env_as_container_ 19777.559 20401.702 20589.856 20606.961 20939.56 21223.502     5
> runBenchmark(2e+4)
Unit: milliseconds
              expr         min         lq        mean    median          uq         max neval
    env_with_list_  534.955014  550.57150  550.329366  553.5288  553.955246  558.636313     5
                c_ 1448.014870 1536.78905 1527.104276 1545.6449 1546.462877 1558.609706     5
             list_    8.746356    8.79615    9.162577    8.8315    9.601226    9.837655     5
          by_index  953.989076 1038.47864 1037.859367 1064.3942 1065.291678 1067.143200     5
           append_ 1634.151839 1682.94746 1681.948374 1689.7598 1696.198890 1706.683874     5
 env_as_container_  204.134468  205.35348  208.011525  206.4490  208.279580  215.841129     5
> 

প্রথমত, মিনিট / এলকিউ / গড় / মিডিয়ান / ইউকিউ / সর্বাধিক মান সম্পর্কে একটি শব্দ: যেহেতু আমরা একটি আদর্শ বিশ্বে 5 রানের প্রত্যেকটির জন্য ঠিক একই কাজটি সম্পাদন করছি, আমরা আশা করতে পারি যে এটি ঠিক একই রকম হবে প্রতিটি রান জন্য সময় পরিমাণ। আমরা যে কোডটি পরীক্ষা করে যাচ্ছি তা এখনও সিপিইউয়ের ক্যাশে লোড করা হয়নি বলে প্রথম রানটি সাধারণত দীর্ঘ সময়ের দিকে পক্ষপাতদুষ্ট থাকে। প্রথম রান অনুসারে, আমরা সময়টি মোটামুটি সুসংগত হওয়ার প্রত্যাশা করতাম, তবে মাঝে মধ্যে টাইমার টিক বিঘ্ন বা আমাদের দ্বারা পরীক্ষিত কোডের সাথে সম্পর্কিত নয় এমন অন্য হার্ডওয়্যার বিঘ্নগুলির কারণে আমাদের কোডটি ক্যাশে থেকে উচ্ছেদ করা যেতে পারে। কোড স্নিপেটগুলি 5 বার পরীক্ষা করে, আমরা প্রথম রান করার সময় কোডটি ক্যাশে লোড করার অনুমতি দিচ্ছি এবং তারপরে প্রতিটি স্নিপেটকে বাইরের ইভেন্টগুলির হস্তক্ষেপ ছাড়াই সম্পূর্ণরূপে চালিত হওয়ার 4 টি সুযোগ দিচ্ছি। এই কারনে,

মনে রাখবেন যে আমি প্রথমে 2000 এবং তার পরে 20000 এর সমস্যার আকার দিয়ে চালানো পছন্দ করেছি, তাই আমার সমস্যাটির আকারটি প্রথম রান থেকে দ্বিতীয় পর্যন্ত 10 এর গুণক দ্বারা বৃদ্ধি পেয়েছে।

listসমাধানের কার্য সম্পাদন : ও (1) (ধ্রুবক সময়)

আসুন প্রথমে listসমাধানটির বৃদ্ধির দিকে নজর দিন , যেহেতু আমরা এখনই বলতে পারি যে এটি উভয় প্রোফাইলিং রানের মধ্যে দ্রুততম সমাধান: প্রথম রানে, 2000 "অ্যাপেন্ড" কার্য সম্পাদন করতে 854 মাইক্রো সেকেন্ড (0.854 মিলি সেকেন্ড) সময় নিয়েছিল । দ্বিতীয় রানটিতে 20000 "সংযোজন" কার্য সম্পাদনের জন্য এটি 8.746 মিলিসেকেন্ড নিয়েছে। একজন নিরীহ পর্যবেক্ষক বলতেন, "আহ, listসমাধানটি ও (এন) এর বৃদ্ধি দেখায়, যেহেতু সমস্যার আকার দশটির একটি ফ্যাক্টর দ্বারা বৃদ্ধি পেয়েছে, তাই পরীক্ষাটি কার্যকর করার জন্য প্রয়োজনীয় সময়ও প্রয়োজন হয়েছিল।" সেই বিশ্লেষণে সমস্যাটি হ'ল ওপি যা চায় তা হ'ল একক বস্তু সন্নিবেশনের বৃদ্ধির হার, সামগ্রিক সমস্যার বৃদ্ধির হার নয়। যে জেনে, এটি পরিষ্কার যে তারপরlist সমাধান ওপি যা চায় ঠিক তা সরবরাহ করে: ও (1) সময়ে কোনও তালিকায় অবজেক্ট যুক্ত করার একটি পদ্ধতি।

অন্যান্য সমাধানের পারফরম্যান্স

অন্য কোনও সমাধান সমাধানের গতির কাছাকাছিও আসে না list, তবে যাইহোক সেগুলি পরীক্ষা করা তথ্যমূলক is

অন্যান্য সমাধানগুলির বেশিরভাগই পারফরম্যান্সে ও (এন) বলে মনে হয়। উদাহরণস্বরূপ, by_indexসমাধান, অন্যান্য এসও পোস্টগুলিতে আমি যে ফ্রিকোয়েন্সিটি পেয়েছি তার উপর ভিত্তি করে একটি খুব জনপ্রিয় সমাধান, 2000 টি অবজেক্ট সংযোজন করতে 11.6 মিলি সেকেন্ড এবং বহু বস্তুর দশগুণ যুক্ত করতে 953 মিলি সেকেন্ড নিয়েছিল। সামগ্রিক সমস্যার সময়টি 100 এর গুণক দ্বারা বৃদ্ধি পেয়েছে, সুতরাং একজন নির্দোষ পর্যবেক্ষক বলতে পারেন "আহ, by_indexসমাধানটি ও (এন 2 ) বৃদ্ধি দেখায়, যেহেতু সমস্যার আকার দশটির একটি ফ্যাক্টর দ্বারা বৃদ্ধি পেয়েছে, পরীক্ষা চালানোর জন্য প্রয়োজনীয় সময়টি বৃদ্ধি পেয়েছে 100 এর ফ্যাক্টর দ্বারা। "আগের মতোই, এই বিশ্লেষণটি ত্রুটিযুক্ত, যেহেতু ওপি একটি একক বস্তুর সন্নিবেশ বৃদ্ধিতে আগ্রহী। যদি আমরা সামগ্রিক সময়ের বৃদ্ধি সমস্যার আকারের বৃদ্ধি দ্বারা বিভক্ত করি তবে আমরা দেখতে পেলাম যে সংযোজন সামগ্রীর সময় বৃদ্ধি কেবলমাত্র 10 এর একটি ফ্যাক্টর দ্বারা বৃদ্ধি পেয়েছে, 100 এর একটি ফ্যাক্টর নয়, যা সমস্যার আকারের বৃদ্ধির সাথে মেলে, তাই by_indexসমাধানটি ও (ঢ)। তালিকাভুক্ত কোনও সমাধান নেই যা একটি একক অবজেক্ট যুক্ত করার জন্য ও (এন 2 ) বৃদ্ধি দেখায়।


1
পাঠককে: দয়া করে জানকানিসের উত্তরটি পড়ুন, যা আমার উপরের গবেষণাগুলিগুলিকে খুব ব্যবহারিক বর্ধিত করে এবং আর এর সি প্রয়োগের অভ্যন্তরীণ কাজকর্মের ফলে বিভিন্ন সমাধানের ওভারহেডে কিছুটা ডুবিয়ে দেয়
ফোনেট্যাগার

4
নিশ্চিত নয় যে তালিকা বিকল্পটি প্রয়োজনীয় যা প্রয়োগ করে:> দৈর্ঘ্য (সি (সি (সি (তালিকা (1)), তালিকা (2)), তালিকা (3))) [1] 3> দৈর্ঘ্য (তালিকা (তালিকা (তালিকা) (তালিকা (1)), তালিকা (2)), তালিকা (3))) [1] ২. নেস্টেড তালিকার মতো আরও দেখতে লাগে L
পিকারাস

@ পিকারাস - আমি মনে করি আপনি ঠিক বলেছেন আমি আর আর নিয়ে কাজ করছি না, তবে কৃতজ্ঞতার সাথে জানকানিস আরও একটি দরকারী ও (1) সমাধান সহ একটি উত্তর পোস্ট করেছেন এবং আপনি চিহ্নিত সমস্যাটি নোট করেছেন। আমি নিশ্চিত জনকানিস আপনার উত্সাহকে প্রশংসা করবে
ফোনেটেগার

@ ফোনেট্যাগার, আপনার উত্তরটি সম্পাদনা করা উচিত। প্রত্যেকেই সমস্ত উত্তর পড়বে না।
পিকারাস

"একটি উত্তরই আসল প্রশ্নকে সম্বোধন করে না" -> সমস্যাটি হ'ল মূল প্রশ্নটি অ্যালগরিদম জটিলতা সম্পর্কে নয়, প্রশ্নের সংস্করণগুলি একবার দেখুন। ওপিতে প্রথমে জিজ্ঞাসা করা হয়েছিল কীভাবে কোনও তালিকায় কোনও উপাদান যুক্ত করা যায়, বেশ কয়েক মাস পরে, তিনি প্রশ্নটি পরিবর্তন করেছিলেন।
কার্লোস সিনেল্লি

41

অন্যান্য উত্তরে, কেবলমাত্র listও (1) সংযোজনে ফলাফলের ফলাফল ঘটে, তবে এটি গভীরভাবে নেস্টেড তালিকার কাঠামোর ফল দেয়, এবং একটি সরল একক তালিকা নয়। আমি নীচের ডেটাস্ট্রাকচারগুলি ব্যবহার করেছি, তারা ও (1) (মোড়িত) সংযোজনকে সমর্থন করে এবং ফলাফলটিকে একটি সরল তালিকায় ফিরে রূপান্তর করতে দেয়।

expandingList <- function(capacity = 10) {
    buffer <- vector('list', capacity)
    length <- 0

    methods <- list()

    methods$double.size <- function() {
        buffer <<- c(buffer, vector('list', capacity))
        capacity <<- capacity * 2
    }

    methods$add <- function(val) {
        if(length == capacity) {
            methods$double.size()
        }

        length <<- length + 1
        buffer[[length]] <<- val
    }

    methods$as.list <- function() {
        b <- buffer[0:length]
        return(b)
    }

    methods
}

এবং

linkedList <- function() {
    head <- list(0)
    length <- 0

    methods <- list()

    methods$add <- function(val) {
        length <<- length + 1
        head <<- list(head, val)
    }

    methods$as.list <- function() {
        b <- vector('list', length)
        h <- head
        for(i in length:1) {
            b[[i]] <- head[[2]]
            head <- head[[1]]
        }
        return(b)
    }
    methods
}

সেগুলি নিম্নলিখিত হিসাবে ব্যবহার করুন:

> l <- expandingList()
> l$add("hello")
> l$add("world")
> l$add(101)
> l$as.list()
[[1]]
[1] "hello"

[[2]]
[1] "world"

[[3]]
[1] 101

এই সমাধানগুলি সম্পূর্ণ বস্তুগুলিতে বিস্তৃত হতে পারে যা নিজেরাই তালিকার সাথে সম্পর্কিত অপারেশনগুলিকে সমর্থন করে তবে এটি পাঠকের জন্য অনুশীলন হিসাবে থাকবে।

নামযুক্ত তালিকার জন্য অন্য একটি রূপ:

namedExpandingList <- function(capacity = 10) {
    buffer <- vector('list', capacity)
    names <- character(capacity)
    length <- 0

    methods <- list()

    methods$double.size <- function() {
        buffer <<- c(buffer, vector('list', capacity))
        names <<- c(names, character(capacity))
        capacity <<- capacity * 2
    }

    methods$add <- function(name, val) {
        if(length == capacity) {
            methods$double.size()
        }

        length <<- length + 1
        buffer[[length]] <<- val
        names[length] <<- name
    }

    methods$as.list <- function() {
        b <- buffer[0:length]
        names(b) <- names[0:length]
        return(b)
    }

    methods
}

benchmarks

@ ফোনেট্যাগারের কোড (যা @ ক্রোন আরকনিসের কোডের উপর ভিত্তি করে) ব্যবহার করে পারফরম্যান্স তুলনা। আমিও একটি যুক্ত করেছি এবং কিছুটা better_env_as_containerপরিবর্তন করেছি env_as_container_। আসলটি env_as_container_ভেঙে গেছে এবং আসলে সমস্ত সংখ্যা সঞ্চয় করে না।

library(microbenchmark)
lPtrAppend <- function(lstptr, lab, obj) {lstptr[[deparse(lab)]] <- obj}
### Store list inside new environment
envAppendList <- function(lstptr, obj) {lstptr$list[[length(lstptr$list)+1]] <- obj} 
env2list <- function(env, len) {
    l <- vector('list', len)
    for (i in 1:len) {
        l[[i]] <- env[[as.character(i)]]
    }
    l
}
envl2list <- function(env, len) {
    l <- vector('list', len)
    for (i in 1:len) {
        l[[i]] <- env[[paste(as.character(i), 'L', sep='')]]
    }
    l
}
runBenchmark <- function(n) {
    microbenchmark(times = 5,  
        env_with_list_ = {
            listptr <- new.env(parent=globalenv())
            listptr$list <- NULL
            for(i in 1:n) {envAppendList(listptr, i)}
            listptr$list
        },
        c_ = {
            a <- list(0)
            for(i in 1:n) {a = c(a, list(i))}
        },
        list_ = {
            a <- list(0)
            for(i in 1:n) {a <- list(a, list(i))}
        },
        by_index = {
            a <- list(0)
            for(i in 1:n) {a[length(a) + 1] <- i}
            a
        },
        append_ = { 
            a <- list(0)    
            for(i in 1:n) {a <- append(a, i)} 
            a
        },
        env_as_container_ = {
            listptr <- new.env(hash=TRUE, parent=globalenv())
            for(i in 1:n) {lPtrAppend(listptr, i, i)} 
            envl2list(listptr, n)
        },
        better_env_as_container = {
            env <- new.env(hash=TRUE, parent=globalenv())
            for(i in 1:n) env[[as.character(i)]] <- i
            env2list(env, n)
        },
        linkedList = {
            a <- linkedList()
            for(i in 1:n) { a$add(i) }
            a$as.list()
        },
        inlineLinkedList = {
            a <- list()
            for(i in 1:n) { a <- list(a, i) }
            b <- vector('list', n)
            head <- a
            for(i in n:1) {
                b[[i]] <- head[[2]]
                head <- head[[1]]
            }                
        },
        expandingList = {
            a <- expandingList()
            for(i in 1:n) { a$add(i) }
            a$as.list()
        },
        inlineExpandingList = {
            l <- vector('list', 10)
            cap <- 10
            len <- 0
            for(i in 1:n) {
                if(len == cap) {
                    l <- c(l, vector('list', cap))
                    cap <- cap*2
                }
                len <- len + 1
                l[[len]] <- i
            }
            l[1:len]
        }
    )
}

# We need to repeatedly add an element to a list. With normal list concatenation
# or element setting this would lead to a large number of memory copies and a
# quadratic runtime. To prevent that, this function implements a bare bones
# expanding array, in which list appends are (amortized) constant time.
    expandingList <- function(capacity = 10) {
        buffer <- vector('list', capacity)
        length <- 0

        methods <- list()

        methods$double.size <- function() {
            buffer <<- c(buffer, vector('list', capacity))
            capacity <<- capacity * 2
        }

        methods$add <- function(val) {
            if(length == capacity) {
                methods$double.size()
            }

            length <<- length + 1
            buffer[[length]] <<- val
        }

        methods$as.list <- function() {
            b <- buffer[0:length]
            return(b)
        }

        methods
    }

    linkedList <- function() {
        head <- list(0)
        length <- 0

        methods <- list()

        methods$add <- function(val) {
            length <<- length + 1
            head <<- list(head, val)
        }

        methods$as.list <- function() {
            b <- vector('list', length)
            h <- head
            for(i in length:1) {
                b[[i]] <- head[[2]]
                head <- head[[1]]
            }
            return(b)
        }

        methods
    }

# We need to repeatedly add an element to a list. With normal list concatenation
# or element setting this would lead to a large number of memory copies and a
# quadratic runtime. To prevent that, this function implements a bare bones
# expanding array, in which list appends are (amortized) constant time.
    namedExpandingList <- function(capacity = 10) {
        buffer <- vector('list', capacity)
        names <- character(capacity)
        length <- 0

        methods <- list()

        methods$double.size <- function() {
            buffer <<- c(buffer, vector('list', capacity))
            names <<- c(names, character(capacity))
            capacity <<- capacity * 2
        }

        methods$add <- function(name, val) {
            if(length == capacity) {
                methods$double.size()
            }

            length <<- length + 1
            buffer[[length]] <<- val
            names[length] <<- name
        }

        methods$as.list <- function() {
            b <- buffer[0:length]
            names(b) <- names[0:length]
            return(b)
        }

        methods
    }

ফলাফল:

> runBenchmark(1000)
Unit: microseconds
                    expr       min        lq      mean    median        uq       max neval
          env_with_list_  3128.291  3161.675  4466.726  3361.837  3362.885  9318.943     5
                      c_  3308.130  3465.830  6687.985  8578.913  8627.802  9459.252     5
                   list_   329.508   343.615   389.724   370.504   449.494   455.499     5
                by_index  3076.679  3256.588  5480.571  3395.919  8209.738  9463.931     5
                 append_  4292.321  4562.184  7911.882 10156.957 10202.773 10345.177     5
       env_as_container_ 24471.511 24795.849 25541.103 25486.362 26440.591 26511.200     5
 better_env_as_container  7671.338  7986.597  8118.163  8153.726  8335.659  8443.493     5
              linkedList  1700.754  1755.439  1829.442  1804.746  1898.752  1987.518     5
        inlineLinkedList  1109.764  1115.352  1163.751  1115.631  1206.843  1271.166     5
           expandingList  1422.440  1439.970  1486.288  1519.728  1524.268  1525.036     5
     inlineExpandingList   942.916   973.366  1002.461  1012.197  1017.784  1066.044     5
> runBenchmark(10000)
Unit: milliseconds
                    expr        min         lq       mean     median         uq        max neval
          env_with_list_ 357.760419 360.277117 433.810432 411.144799 479.090688 560.779139     5
                      c_ 685.477809 734.055635 761.689936 745.957553 778.330873 864.627811     5
                   list_   3.257356   3.454166   3.505653   3.524216   3.551454   3.741071     5
                by_index 445.977967 454.321797 515.453906 483.313516 560.374763 633.281485     5
                 append_ 610.777866 629.547539 681.145751 640.936898 760.570326 763.896124     5
       env_as_container_ 281.025606 290.028380 303.885130 308.594676 314.972570 324.804419     5
 better_env_as_container  83.944855  86.927458  90.098644  91.335853  92.459026  95.826030     5
              linkedList  19.612576  24.032285  24.229808  25.461429  25.819151  26.223597     5
        inlineLinkedList  11.126970  11.768524  12.216284  12.063529  12.392199  13.730200     5
           expandingList  14.735483  15.854536  15.764204  16.073485  16.075789  16.081726     5
     inlineExpandingList  10.618393  11.179351  13.275107  12.391780  14.747914  17.438096     5
> runBenchmark(20000)
Unit: milliseconds
                    expr         min          lq       mean      median          uq         max neval
          env_with_list_ 1723.899913 1915.003237 1921.23955 1938.734718 1951.649113 2076.910767     5
                      c_ 2759.769353 2768.992334 2810.40023 2820.129738 2832.350269 2870.759474     5
                   list_    6.112919    6.399964    6.63974    6.453252    6.910916    7.321647     5
                by_index 2163.585192 2194.892470 2292.61011 2209.889015 2436.620081 2458.063801     5
                 append_ 2832.504964 2872.559609 2983.17666 2992.634568 3004.625953 3213.558197     5
       env_as_container_  573.386166  588.448990  602.48829  597.645221  610.048314  642.912752     5
 better_env_as_container  154.180531  175.254307  180.26689  177.027204  188.642219  206.230191     5
              linkedList   38.401105   47.514506   46.61419   47.525192   48.677209   50.952958     5
        inlineLinkedList   25.172429   26.326681   32.33312   34.403442   34.469930   41.293126     5
           expandingList   30.776072   30.970438   34.45491   31.752790   38.062728   40.712542     5
     inlineExpandingList   21.309278   22.709159   24.64656   24.290694   25.764816   29.158849     5

আমি যোগ করেছি linkedListএবং expandingListএবং উভয়ের একটি অন্তর্ভুক্ত সংস্করণ। inlinedLinkedListমূলত একটি অনুলিপি list_, কিন্তু এটি একটি প্লেইন তালিকায় নেস্টেড গঠন ফিরে পরিবর্তন করে। এর বাইরে ইনলাইনড এবং অন-ইনলাইনড সংস্করণগুলির মধ্যে পার্থক্যটি ফাংশন কলগুলির ওভারহেডের কারণে।

সমস্ত রূপ এবং expandingListlinkedList(1) পরিচ্ছন্নতা প্রদর্শন, বেনমার্ক সময় যুক্ত আইটেম সংখ্যার সাথে রৈখিকভাবে স্কেলিং সঙ্গে। linkedListএর চেয়ে ধীরে ধীরে expandingListএবং ফাংশন কল ওভারহেডটিও দৃশ্যমান। সুতরাং আপনি যদি পেতে পারেন এমন সমস্ত গতি যদি সত্যিই প্রয়োজন হয় (এবং আর কোডটি আটকে রাখতে চান) তবে এর ইনলাইনড সংস্করণ ব্যবহার করুন expandingList

আমি আর এর সি বাস্তবায়নের দিকেও নজর রেখেছি এবং আপনার স্মৃতিশক্তি শেষ না হওয়া পর্যন্ত উভয় পদ্ধতিরই (1) কোনও আকারের জন্য সংযোজন করা উচিত।

আমিও বদলেছি env_as_container_, আসল সংস্করণটি প্রতিটি আইটেমকে সূচক "i" এর অধীনে সংরক্ষণ করবে, পূর্বে সংযুক্ত আইটেমটি ওভাররাইট করে। better_env_as_containerআমি যোগ করেছি খুব অনুরূপ env_as_container_কিন্তু ছাড়া deparseস্টাফ। উভয়ই ও (1) পারফরম্যান্স প্রদর্শন করে তবে তাদের ওভারহেড রয়েছে যা সংযুক্ত / প্রসারিত তালিকার তুলনায় বেশ খানিকটা বড়।

মেমরি ওভারহেড

সিআর বাস্তবায়নে বরাদ্দকৃত বস্তুতে 4 টি শব্দের ও 2 ইনটসের ওভারহেড থাকে। linkedListপদ্ধতির বরাদ্দ এক পরিশেষে যোগ প্রতি দৈর্ঘ্য দুই তালিকা, (4 * 8 + 4 + 4 + 2 * 8 =) তাই সম্ভবত 64 কাছাকাছি 64-বিট কম্পিউটার (মেমরি অ্যালোকেশন ওভারহেড ব্যতীত উপর যোগ করা আইটেম প্রতি 56 বাইট, মোট বাইটস)। expandingListপদ্ধতির যোগ আইটেম প্রতি এক শব্দ, প্লাস একটি কপি যখন ভেক্টর দৈর্ঘ্য দ্বিগুন ব্যবহার করে, তাই আইটেম প্রতি 16 বাইট পর্যন্ত মোট মেমোরি ব্যবহার। যেহেতু স্মৃতি সমস্ত এক বা দুটি বস্তুর মধ্যে প্রতি-অবজেক্টের ওভারহেড তুচ্ছ। আমি envমেমরির ব্যবহারের দিকে গভীরভাবে নজর রাখিনি , তবে আমি মনে করি এটি আরও ঘনিষ্ঠ হবে linkedList


তালিকার বিকল্পটি রাখার কী আছে যদি এটি সমস্যার সমাধান না করে যা আমরা সমাধান করার চেষ্টা করছি?
পিকারাস

1
@ পিকারাস আমি নিশ্চিত না যে আপনি কী বলছেন। কেন আমি এটি বেঞ্চমার্কে রেখেছি? অন্যান্য বিকল্পের সাথে তুলনা হিসাবে। list_বিকল্প দ্রুততর ও উপযোগী হতে পারে যদি আপনি অর্থাত, একটি স্বাভাবিক লিস্টে রূপান্তর করতে প্রয়োজন হবে না যদি আপনি একটি স্ট্যাক হিসাবে ফলাফলের ব্যবহার করুন।
জানকানিস

@ গাবর সিসারদী পরিবেশকে পরিবেশনাগুলিকে স্ট্যাকওভারফ্লো.com/a/29482211/264177- এ একটি পৃথক প্রশ্নের তালিকায় ফিরে যেতে দ্রুততর পোস্ট করেছেন। আমি আমার সিস্টেমে সেটিও বেঞ্চমার্ক করেছি। এটি প্রায় দ্বিগুণ দ্রুততর উন্নত_এনভি_স_ কনটেনার তবে লিঙ্কযুক্ত তালিকা এবং সম্প্রসারণ তালিকার চেয়ে এখনও ধীর।
জানকানিস

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

17

লিস্পে আমরা এটি এভাবে করেছি:

> l <- c(1)
> l <- c(2, l)
> l <- c(3, l)
> l <- rev(l)
> l
[1] 1 2 3

যদিও এটি 'কনস' ছিল, কেবল 'সি' নয়। যদি আপনাকে একটি খালি তালিকা দিয়ে শুরু করতে হয় তবে l <- NULL ব্যবহার করুন।


3
অসাধারণ! অন্যান্য সমস্ত সমাধান তালিকার কিছু অদ্ভুত তালিকা ফিরিয়ে দেয়।
metakermit

4
লিস্পে, একটি তালিকা প্রস্তুত করা হ'ল একটি ও (1) অপারেশন, যখন ও (এন), @ ফ্লাইসে সঞ্চালিত হয়। পারফরম্যান্স লাভের ফলে বিপরীত হওয়ার প্রয়োজনীয়তা অতিক্রম করা হয়। এটি আর এর ক্ষেত্রে নয়, এমনকি প্যারেলিস্টেও নয়, যা সাধারণত তালিকার তালিকার সাদৃশ্যযুক্ত।
প্যালেক

@ পোলেক "আর-তে এটি নয়" - আপনি কোন "এটি" উল্লেখ করছেন তা নিশ্চিত নই। আপনি কি বলছেন যে সংযোজন ও (1) নয়, বা এটি ও (এন) নয়?
উড়ে

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

3
আর এ, এই পদ্ধতির ও (এন) হবে। c()একটি নতুন ভেক্টর / তালিকায় ফাংশন কপি এর আর্গুমেন্টগুলি এবং আয় হয়।
জানকানিস

6

আপনি কি এই জাতীয় কিছু চান?

> push <- function(l, x) {
   lst <- get(l, parent.frame())
   lst[length(lst)+1] <- x
   assign(l, lst, envir=parent.frame())
 }
> a <- list(1,2)
> push('a', 6)
> a
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 6

এটি খুব বিনীত ফাংশন নয় (নির্ধারণ করা parent.frame()এক ধরণের অভদ্রতা) তবে IIUYC এটি যা আপনি জিজ্ঞাসা করছেন।


6

আমি এখানে উল্লিখিত পদ্ধতির একটি ছোট তুলনা করেছি।

n = 1e+4
library(microbenchmark)
### Using environment as a container
lPtrAppend <- function(lstptr, lab, obj) {lstptr[[deparse(substitute(lab))]] <- obj}
### Store list inside new environment
envAppendList <- function(lstptr, obj) {lstptr$list[[length(lstptr$list)+1]] <- obj} 

microbenchmark(times = 5,  
        env_with_list_ = {
            listptr <- new.env(parent=globalenv())
            listptr$list <- NULL
            for(i in 1:n) {envAppendList(listptr, i)}
            listptr$list
        },
        c_ = {
            a <- list(0)
            for(i in 1:n) {a = c(a, list(i))}
        },
        list_ = {
            a <- list(0)
            for(i in 1:n) {a <- list(a, list(i))}
        },
        by_index = {
            a <- list(0)
            for(i in 1:n) {a[length(a) + 1] <- i}
            a
        },
        append_ = { 
            a <- list(0)    
            for(i in 1:n) {a <- append(a, i)} 
            a
        },
        env_as_container_ = {
            listptr <- new.env(parent=globalenv())
            for(i in 1:n) {lPtrAppend(listptr, i, i)} 
            listptr
        }   
)

ফলাফল:

Unit: milliseconds
              expr       min        lq       mean    median        uq       max neval cld
    env_with_list_  188.9023  198.7560  224.57632  223.2520  229.3854  282.5859     5  a 
                c_ 1275.3424 1869.1064 2022.20984 2191.7745 2283.1199 2491.7060     5   b
             list_   17.4916   18.1142   22.56752   19.8546   20.8191   36.5581     5  a 
          by_index  445.2970  479.9670  540.20398  576.9037  591.2366  607.6156     5  a 
           append_ 1140.8975 1316.3031 1794.10472 1620.1212 1855.3602 3037.8416     5   b
 env_as_container_  355.9655  360.1738  399.69186  376.8588  391.7945  513.6667     5  a 

এটি দুর্দান্ত তথ্য: কখনই অনুমান করতে পারতেন না যে কেবল বিজয়ীই list = listছিলেন না - তবে 1 থেকে 2 অর্ডার বা পরিমাণের দ্বারা!
জাভাদবা

5

যদি আপনি উদ্ধৃত স্ট্রিং হিসাবে তালিকার ভেরিয়েবলটিতে পাস করেন তবে আপনি এটির মতো ফাংশন থেকে এটি পৌঁছাতে পারেন:

push <- function(l, x) {
  assign(l, append(eval(as.name(l)), x), envir=parent.frame())
}

তাই:

> a <- list(1,2)
> a
[[1]]
[1] 1

[[2]]
[1] 2

> push("a", 3)
> a
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

> 

বা অতিরিক্ত creditণের জন্য:

> v <- vector()
> push("v", 1)
> v
[1] 1
> push("v", 2)
> v
[1] 1 2
> 

1
এটি মূলত আমি যে আচরণটি চাই তা হ'ল এটি এখনও অভ্যন্তরীণভাবে সংযোজন করাকে কল করে যার ফলশ্রুতি ও (এন ^ 2) হয়।
নিক

4

নিশ্চিত না যে আপনি কেন মনে করেন না যে আপনার প্রথম পদ্ধতিটি কাজ করবে না। ল্যাপেন্ড ফাংশনে আপনার একটি বাগ রয়েছে: দৈর্ঘ্য (তালিকা) দৈর্ঘ্য হওয়া উচিত (lst)। এটি সূক্ষ্মভাবে কাজ করে এবং সংযুক্ত আপত্তি সহ একটি তালিকা দেয়।


3
তুমি একদম সঠিক. কোডটিতে একটি বাগ ছিল এবং আমি এটি ঠিক করেছি fixed আমি lappend()যেটি সরবরাহ করেছি তা পরীক্ষা করেছি এবং এটি সি () এবং পরিশিষ্ট () হিসাবে প্রায় সমস্ত সম্পাদন করে যা ও (এন ^ 2) আচরণ প্রদর্শন করে।
নিক


2

আমি মনে করি আপনি যা করতে চান তা আসলে ফাংশনটিতে রেফারেন্স (পয়েন্টার) দিয়ে যেতে হবে - তালিকার সাথে যোগ করা তালিকার সাথে একটি নতুন পরিবেশ তৈরি করুন (যা ফাংশনগুলির রেফারেন্স দিয়ে পাস হয়) তৈরি করুন:

listptr=new.env(parent=globalenv())
listptr$list=mylist

#Then the function is modified as:
lPtrAppend <- function(lstptr, obj) {
    lstptr$list[[length(lstptr$list)+1]] <- obj
}

এখন আপনি কেবল বিদ্যমান তালিকাটি সংশোধন করছেন (কোনও নতুন তৈরি করবেন না)


1
এটি আবার চতুর্ভুজ সময় জটিলতা বলে মনে হয়। স্পষ্টতই সমস্যাটি হল যে তালিকা / ভেক্টরের আকার পরিবর্তনটি সাধারণত বেশিরভাগ ভাষায় প্রয়োগ করা হয় না।
eold

হ্যাঁ - শেষের দিকে সংযোজনটি খুব ধীর - সম্ভবত খ / সি তালিকাগুলি পুনরাবৃত্ত হয় এবং লুপ টাইপের ক্রিয়াকলাপের চেয়ে ভেক্টর ক্রিয়াকলাপে আর সেরা best এটি করা আরও ভাল:
ডেভিডএম

1
system.time ((আমি সি (1: 10000) মাইলিস্টের জন্য [i] = i) (কয়েক সেকেন্ড), বা আরও ভাল এটি সমস্তই একটি ক্রিয়াকলাপে: system.টাইম (মাইলিস্ট = তালিকা (1: 100000)) (এক সেকেন্ডেরও কম), তারপরে লুপের জন্য পূর্বনির্ধারিত তালিকার সংশোধন করা আরও দ্রুত হবে
ডেভিডএম

2

এটি কোনও আর তালিকার আইটেম যুক্ত করার সহজ সরল উপায়:

# create an empty list:
small_list = list()

# now put some objects in it:
small_list$k1 = "v1"
small_list$k2 = "v2"
small_list$k3 = 1:10

# retrieve them the same way:
small_list$k1
# returns "v1"

# "index" notation works as well:
small_list["k2"]

বা প্রোগ্রামগতভাবে:

kx = paste(LETTERS[1:5], 1:5, sep="")
vx = runif(5)
lx = list()
cn = 1

for (itm in kx) { lx[itm] = vx[cn]; cn = cn + 1 }

print(length(lx))
# returns 5

এটি আসলে সংযোজনযোগ্য নয়। আমার যদি 100 টি বস্তু থাকে এবং আমি সেগুলি প্রোগ্রামে কোনও তালিকায় যুক্ত করতে চাই? আর এর একটি append()ফাংশন রয়েছে তবে এটি সত্যিই একটি সংযুক্ত ফাংশন এবং এটি কেবল ভেক্টরগুলিতেই কাজ করে।
নিক

append()ভেক্টর এবং তালিকাগুলিতে কাজ করে, এবং এটি একটি সত্য সংযোজন (যা মূলত কনকানেটের সমান, তাই আপনার সমস্যাটি কী তা আমি দেখতে পাচ্ছি না)
হ্যাডলি

8
একটি অ্যাপেন্ড ফাংশন একটি বিদ্যমান বস্তুর পরিবর্তন করতে হবে, একটি নতুন তৈরি না করে। সত্যিকারের সংযোজনে O (N ^ 2) আচরণ হবে না।
নিক

2

আসলে c()ফাংশন সহ একটি subtlety আছে । যদি তুমি করো:

x <- list()
x <- c(x,2)
x = c(x,"foo")

আপনি আশানুরূপ হিসাবে পাবেন:

[[1]]
[1]

[[2]]
[1] "foo"

তবে আপনি যদি একটি ম্যাট্রিক্স যুক্ত করেন তবে x <- c(x, matrix(5,2,2)আপনার তালিকায় আরও 4 টির মূল্যের উপাদান থাকবে 5! আপনি আরও ভাল করতে হবে:

x <- c(x, list(matrix(5,2,2))

এটি অন্য যে কোনও অবজেক্টের জন্য কাজ করে এবং আপনি প্রত্যাশা অনুযায়ী পাবেন:

[[1]]
[1]

[[2]]
[1] "foo"

[[3]]
     [,1] [,2]
[1,]    5    5
[2,]    5    5

অবশেষে, আপনার ফাংশনটি হয়ে যায়:

push <- function(l, ...) c(l, list(...))

এবং এটি যে কোনও ধরণের অবজেক্টের জন্য কাজ করে। আপনি বুদ্ধিমান হতে এবং করতে পারেন:

push_back <- function(l, ...) c(l, list(...))
push_front <- function(l, ...) c(list(...), l)

1

এর list.appendথেকেও রয়েছে rlist( ডকুমেন্টেশনের লিঙ্ক )

require(rlist)
LL <- list(a="Tom", b="Dick")
list.append(LL,d="Pam",f=c("Joe","Ann"))

এটি খুব সহজ এবং দক্ষ।


1
আমার কাছে আর কি লাগছে না ... পাইথন?
জেডি লং

1
আমি একটি সম্পাদনা করেছি এবং এটি চেষ্টা করে দেখলাম: এটি ধীরে ধীরে কমছে। c()বা- listআদর্শ ব্যবহার করুন । উভয়ই পথ দ্রুত।
5 ই

কোডটি খুঁজছেন rlist::list.append(), এটি মূলত চারপাশে একটি মোড়ক base::c()
nbenn

1

বৈধতার জন্য আমি @ ক্রোন দ্বারা সরবরাহিত বেঞ্চমার্ক কোডটি চালিয়েছি। এর মধ্যে একটি প্রধান পার্থক্য রয়েছে (নতুন আই 7 প্রসেসরের দ্রুত চালানো ছাড়াও): by_indexএখন প্রায় পাশাপাশি সম্পাদন করে list_:

Unit: milliseconds
              expr        min         lq       mean     median         uq
    env_with_list_ 167.882406 175.969269 185.966143 181.817187 185.933887
                c_ 485.524870 501.049836 516.781689 518.637468 537.355953
             list_   6.155772   6.258487   6.544207   6.269045   6.290925
          by_index   9.290577   9.630283   9.881103   9.672359  10.219533
           append_ 505.046634 543.319857 542.112303 551.001787 553.030110
 env_as_container_ 153.297375 154.880337 156.198009 156.068736 156.800135

রেফারেন্সের জন্য এখানে @ ক্রোন এর উত্তর থেকে বেনমার্ক কোড অনুলিপি করা ভারব্যাটিম (ঠিক পরে যদি তিনি বিষয়বস্তু পরিবর্তন করেন তবে):

n = 1e+4
library(microbenchmark)
### Using environment as a container
lPtrAppend <- function(lstptr, lab, obj) {lstptr[[deparse(substitute(lab))]] <- obj}
### Store list inside new environment
envAppendList <- function(lstptr, obj) {lstptr$list[[length(lstptr$list)+1]] <- obj}

microbenchmark(times = 5,
        env_with_list_ = {
            listptr <- new.env(parent=globalenv())
            listptr$list <- NULL
            for(i in 1:n) {envAppendList(listptr, i)}
            listptr$list
        },
        c_ = {
            a <- list(0)
            for(i in 1:n) {a = c(a, list(i))}
        },
        list_ = {
            a <- list(0)
            for(i in 1:n) {a <- list(a, list(i))}
        },
        by_index = {
            a <- list(0)
            for(i in 1:n) {a[length(a) + 1] <- i}
            a
        },
        append_ = {
            a <- list(0)
            for(i in 1:n) {a <- append(a, i)}
            a
        },
        env_as_container_ = {
            listptr <- new.env(parent=globalenv())
            for(i in 1:n) {lPtrAppend(listptr, i, i)}
            listptr
        }
)

0
> LL<-list(1:4)

> LL

[[1]]
[1] 1 2 3 4

> LL<-list(c(unlist(LL),5:9))

> LL

[[1]]
 [1] 1 2 3 4 5 6 7 8 9

2
আমি মনে করি না যে এটি ওপিকে সংযোজন করার ধরণ ছিল।
জোরান

এটি কোনও তালিকার উপাদানগুলিকে সংযোজন করছে না। এখানে আপনি পূর্ণসংখ্যার ভেক্টরের উপাদানগুলি বৃদ্ধি করছেন যা তালিকার একমাত্র উপাদান। তালিকার একটিমাত্র উপাদান, একটি পূর্ণসংখ্যার ভেক্টর রয়েছে।
সার্জিও

0

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

a_list<-list()
for(i in 1:3){
  a_list<-list(unlist(list(unlist(a_list,recursive = FALSE),list(rnorm(2))),recursive = FALSE))
}
a_list

[[1]]
[[1]][[1]]
[1] -0.8098202  1.1035517

[[1]][[2]]
[1] 0.6804520 0.4664394

[[1]][[3]]
[1] 0.15592354 0.07424637

আমি কী যুক্ত করতে চাই তা এটি একটি দুটি স্তরের নেস্টেড তালিকা দেয় না, তবে এটি but কীভাবে তালিকাভুক্তি এবং তালিকাভুক্তি কাজ করে তা আমার কাছে খুব পরিষ্কার নয় তবে এই কোডটি পরীক্ষা করে ফলাফল
xappppp

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.