তালিকার উপাদান উপস্থিত থাকলে কীভাবে পরীক্ষা করবেন?


113

সমস্যা

আমি যদি একটি তালিকার একটি উপাদান উপস্থিত থাকে তা পরীক্ষা করতে চাই, এখানে একটি উদাহরণ

foo <- list(a=1)
exists('foo') 
TRUE   #foo does exist
exists('foo$a') 
FALSE  #suggests that foo$a does not exist
foo$a
[1] 1  #but it does exist

এই উদাহরণে, আমি জানি যে foo$aবিদ্যমান, কিন্তু পরীক্ষা ফিরে FALSE

আমি সন্ধান করেছিলাম ?existsএবং with(foo, exists('a')ফিরে পেয়েছি TRUE, কিন্তু কেন exists('foo$a')ফিরে আসে তা বুঝতে পারি না FALSE

প্রশ্নাবলি

  • exists('foo$a')ফিরে আসে কেন FALSE?
  • with(...)পছন্দসই পদ্ধতির ব্যবহার কি ?

1
হতে পারে !is.null(foo$a)(বা !is.null(foo[["a"]])নিরাপদ দিকে হতে)? (বা exists("a",where=foo))
বেন বোলকার

1
@ বেনবোলকার ধন্যবাদ - একটি ভাল উত্তর দিতে হবে; পরের বিকল্পটি কেন পছন্দ করা হয়?
ডেভিড লেবাউর

3
@David আংশিক ম্যাচিং ... সাথে উপরে চেষ্টাfoo <- list(a1=1)
Baptiste

উত্তর:


151

এটি আসলে আপনি যা ভাবেন তার চেয়ে কিছুটা জটিল। যেহেতু একটি তালিকাতে আসলে (কিছু চেষ্টা করে) নুল উপাদান থাকতে পারে, তাই এটি যাচাইয়ের পক্ষে যথেষ্ট নাও হতে পারে is.null(foo$a)। নামটি তালিকায় নামটি আসলে সংজ্ঞায়িত করা হয়েছে কি না তা পরীক্ষা করার জন্য আরও কঠোর পরীক্ষা হতে পারে:

foo <- list(a=42, b=NULL)
foo

is.null(foo[["a"]]) # FALSE
is.null(foo[["b"]]) # TRUE, but the element "exists"...
is.null(foo[["c"]]) # TRUE

"a" %in% names(foo) # TRUE
"b" %in% names(foo) # TRUE
"c" %in% names(foo) # FALSE

... এবং এর foo[["a"]]চেয়ে সুরক্ষিত foo$a, যেহেতু পরেরটি আংশিক মিল ব্যবহার করে এবং এর ফলে এটি আরও দীর্ঘ নামের সাথেও মেলে:

x <- list(abc=4)
x$a  # 4, since it partially matches abc
x[["a"]] # NULL, no match

[আপডেট] সুতরাং, কেন exists('foo$a')কাজ করে না এমন প্রশ্নে ফিরে যান । existsফাংশন শুধুমাত্র চেক একটি পরিবর্তনশীল একটি পরিবেশ যদি উপস্থিত থাকে, যদি না একটি বস্তুর অস্তিত্ব অংশগুলি। স্ট্রিংটি "foo$a"ব্যাখ্যা করা হয় সাহিত্যিক: "foo $ a" নামে একটি পরিবর্তনশীল আছে? ... এবং উত্তরটি হ'ল FALSE...

foo <- list(a=42, b=NULL) # variable "foo" with element "a"
"bar$a" <- 42   # A variable actually called "bar$a"...
ls() # will include "foo" and "bar$a" 
exists("foo$a") # FALSE 
exists("bar$a") # TRUE

2
এটি এখনও পরিষ্কার নয় - এর কোনও কারণ আছে exists('foo$a') == FALSEকি?
ডেভিড লেবাউর

এটি সুপারিশ করে যে আর এর জন্য সাধারণত এর জন্য কোনও ভাল সমাধান নেই! কেউ আরও জটিল জিনিস ( $mylist[[12]]$out$mcerrorযেমন সংজ্ঞায়িত হলে পরীক্ষার মতো ) চাইবে যা বর্তমানে নরক হিসাবে জটিল হতে পারে।
টিএমএস

@ জিমের উত্তরে আপনি কী whereযুক্তি দেখানোর বিষয়ে অবগত ছিলেন ? exists
ডেভিড লেবাউর

"bar$a" <- 42আমি সত্যিই চাই যে এটি অবৈধ বাক্য গঠন ছিল এবং বিদ্যমান ("foo $ a") নিষ্পাপ অর্থে কাজ করেছিল।
অ্যান্ডি ভি

44

নামযুক্ত উপাদানগুলির জন্য চেক করার সর্বোত্তম উপায়টি হ'ল ব্যবহার করা exist(), তবে উপরের উত্তরগুলি সঠিকভাবে ফাংশনটি ব্যবহার করছে না। তালিকার মধ্যেwhere চলকটি পরীক্ষা করতে আপনাকে যুক্তিটি ব্যবহার করতে হবে ।

foo <- list(a=42, b=NULL)

exists('a', where=foo) #TRUE
exists('b', where=foo) #TRUE
exists('c', where=foo) #FALSE

8
ব্যবহার exists()তালিকায় কাজ করে, কিন্তু আমি বিশ্বাস করি যে আর অভ্যন্তরীণভাবে সেই নামের একটি বস্তু, যা অদক্ষ এবং ত্রুটি হতে পারে যদি কোনো নামহীন উপাদানের জন্য প্রত্যাহার পরীক্ষার আগে একটি পরিবেশ এটা coerces। উদাহরণস্বরূপ, যদি আপনি চালানোর জন্য exists('a', list(a=1, 2)), এটি একটি ত্রুটির দিতে হবে: Error in list2env(list(a = 1, 2), NULL, <environment>) : attempt to use zero-length variable name। রূপান্তরটি এখানে ঘটে: github.com/wch/r-source/blob/…
wch

5

অন্যান্য উত্তরের প্রস্তাবিত পদ্ধতির একটি পারফরম্যান্স তুলনা এখানে।

> foo <- sapply(letters, function(x){runif(5)}, simplify = FALSE)
> microbenchmark::microbenchmark('k' %in% names(foo), 
                                 is.null(foo[['k']]), 
                                 exists('k', where = foo))
Unit: nanoseconds
                     expr  min   lq    mean median   uq   max neval cld
      "k" %in% names(foo)  467  933 1064.31    934  934 10730   100  a 
      is.null(foo[["k"]])    0    0  168.50      1  467  3266   100  a 
 exists("k", where = foo) 6532 6998 7940.78   7232 7465 56917   100   b

আপনি যদি দ্রুত অভিধানটি বহুবার অ্যাক্সেস করা হিসাবে তালিকাটি ব্যবহার করার পরিকল্পনা করে থাকেন তবে is.nullপদ্ধতির একমাত্র কার্যকর বিকল্প হতে পারে। আমি ধরে নিলাম এটি ও (1), তবে %in%পদ্ধতির ও (এন) রয়েছে?


4

@ স্যালিয়েন্ট.সালামান্ডারের একটি সামান্য সংশোধিত সংস্করণ, যদি কেউ পুরো পথে চেক করতে চান তবে এটি ব্যবহার করা যেতে পারে।

Element_Exists_Check = function( full_index_path ){
  tryCatch({
    len_element = length(full_index_path)
    exists_indicator = ifelse(len_element > 0, T, F)
      return(exists_indicator)
  }, error = function(e) {
    return(F)
  })
}

3

একটি সমাধান যা এখনও আসে নি তা হ'ল দৈর্ঘ্যটি ব্যবহার করে যা সফলভাবে NULL পরিচালনা করে। আমি যতদূর বলতে পারি, NULL বাদে সমস্ত মানগুলির দৈর্ঘ্য 0 এর চেয়ে বেশি।

x <- list(4, -1, NULL, NA, Inf, -Inf, NaN, T, x = 0, y = "", z = c(1,2,3))
lapply(x, function(el) print(length(el)))
[1] 1
[1] 1
[1] 0
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 1
[1] 3

সুতরাং আমরা একটি সাধারণ ক্রিয়াকলাপ করতে পারি যা নাম এবং সংখ্যায়িত সূচক উভয়ের সাথেই কাজ করে:

element.exists <- function(var, element)
{
  tryCatch({
    if(length(var[[element]]) > -1)
      return(T)
  }, error = function(e) {
    return(F)
  })
}

যদি উপাদানটি বিদ্যমান না থাকে, এটি ট্রাইচ্যাচ ব্লক দ্বারা ধরা একটি বাহ্যিক সীমার শর্ত সৃষ্টি করে।


3

rlang::has_name() এটিও করতে পারেন:

foo = list(a = 1, bb = NULL)
rlang::has_name(foo, "a")  # TRUE
rlang::has_name(foo, "b")  # FALSE. No partial matching
rlang::has_name(foo, "bb")  # TRUE. Handles NULL correctly
rlang::has_name(foo, "c")  # FALSE

আপনি দেখতে পাচ্ছেন, এটি অন্তর্নিহিত সমস্ত কেস পরিচালনা করে যা @ টমি দেখিয়েছিল কীভাবে বেস আর ব্যবহার করে পরিচালনা করতে হবে এবং নামবিহীন আইটেমগুলির সাথে তালিকার জন্য কাজ করে works আমি এখনও exists("bb", where = foo)পঠনযোগ্যতার জন্য অন্য উত্তরে প্রস্তাবিত হিসাবে প্রস্তাব করব, তবে has_nameআপনার কাছে নামবিহীন আইটেম থাকলে বিকল্প alternative


0

একটি তালিকা উপাদানের মানpurrr::has_element বিরুদ্ধে পরীক্ষা করতে ব্যবহার করুন :

> x <- list(c(1, 2), c(3, 4))
> purrr::has_element(x, c(3, 4))
[1] TRUE
> purrr::has_element(x, c(3, 5))
[1] FALSE

উপাদানটি বাসা বেঁধে / নীড়ের কোনও স্তরে থাকলে কী কাজ করে? আমি দস্তাবেজগুলি পরীক্ষা করেছিলাম এবং এটি পরিষ্কার ছিল না
ডেভিড লেবাউর

@ ডেভিডলেবাউর, না। rapplyany(rapply(x, function(v) identical(v, c(3, 4)), how = 'unlist'))
সেক্ষেত্রে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.