【问题标题】:find a previous element if an element is undefined in HashMap如果元素在 HashMap 中未定义,则查找前一个元素
【发布时间】:2020-06-24 03:11:17
【问题描述】:

我有一个 HashMap

const hash = {
  "00:00": "Hello",
  "00:01": "Every one",
  "00:04": "Nice to meet you",
  "00:10": "Could you introduce yourself?",
  "00:23": "Hi, My name is HashMap"
}
console.log(hash["00:00"]);
console.log(hash["00:01"]);
console.log(hash["00:04"]);
console.log(hash["00:05"]); // it returns `undefined`, so it should find previous element. in this case "00:04"
console.log(hash["00:10"]);
console.log(hash["00:17"]); // it also returns `undefined`, it should find "00:10" element.
console.log(hash["00:19"]); // it also should find "00:10" element.
console.log(hash["00:22"]); // it also should find "00:10" element.
console.log(hash["00:23"]); 

提前致谢

已编辑

我不想迭代所有元素。因为它对HashMap没有意义。

【问题讨论】:

  • 赞成,但我不确定哈希图是否是解决此问题的正确数据结构。我认为您可能需要订购时间键。
  • “我不想迭代所有元素。因为它对 HashMap 没有意义”...根据那个逻辑,“前一个元素” 也没有任何意义。
  • @GerardoFurtado 我明白,我只是想知道任何“特殊算法”。因为我不知道这个世界上的每一种算法。
  • @GerardoFurtado 所以你的意思是,没有办法用时间复杂度O(1)O(n) 来解决我的问题?
  • 你可以使用库吗?

标签: javascript hashmap


【解决方案1】:

const hash = {
  "00:00": "Hello",
  "00:01": "Every one",
  "00:04": "Nice to meet you",
  "00:10": "Could you introduce yourself?",
  "00:23": "Hi, My name is HashMap"
}


function x(time, check) {
    var prev = -1;
    var i;
    for (i in time) {
        var n = i;
        if ((prev != -1) && (check < n))
            return prev;
        else 
            prev = n;
    }
}

console.log(x(hash, "00:05"));

【讨论】:

  • 谢谢你的回答,但我不想迭代所有元素。
【解决方案2】:

您应该可以使用Proxy。它允许您拦截和重新定义对对象的操作。使用您的示例,它可能看起来像这样:

let hash = {
  "00:00": "Hello",
  "00:01": "Every one",
  "00:04": "Nice to meet you",
  "00:10": "Could you introduce yourself?",
  "00:23": "Hi, My name is HashMap"
}
const handler = {
  // Keeps track of last property accessed
  last: undefined,
  get: function (obj, prop) {
    if (prop in obj) {
      // Exists, so update last accessed property
      this.last = obj[prop];
      return obj[prop];
    }
    // Because there is no matching property, return last accessed
    return this.last;
  }
}
// Implement proxy
hash = new Proxy(hash, handler);

console.log(hash["00:00"]);  // Hello
console.log(hash["00:01"]);  // Every  one
console.log(hash["00:04"]);  // Nice to meet you
console.log(hash["00:05"]);  // Nice to meet you
console.log(hash["00:10"]);  // Could you introduce yourself?
console.log(hash["00:17"]);  // Could you introduce yourself?
console.log(hash["00:19"]);  // Could you introduce yourself?
console.log(hash["00:22"]);  // Could you introduce yourself?
console.log(hash["00:23"]);  // Hi, My name is HashMap

编辑(澄清问题后)

要找到最近的前一个属性,不涉及迭代至少一些键的工作要做的很多。此实现使用二分搜索,但我认为根据Object.keys() 的可能定义,它仍会被视为O(n)。我将键值增加了一个小时,因此您会看到尝试访问小于任何定义的值的结果。

let hash = {
  "01:00": "Hello",
  "01:01": "Every one",
  "01:04": "Nice to meet you",
  "01:10": "Could you introduce yourself?",
  "01:23": "Hi, My name is HashMap"
}
const handler = {
  get: function (obj, prop) {
    if (obj[prop] !== undefined) {
      return obj[prop];
    } else {
      // Validate input format before bothering to search
      if (/\d{2}:\d{2}/.test(prop) !== true) return undefined;
      
      // Search for nearest previous property
      const keys = Object.keys(obj);
      return obj[findPrevious(keys, prop, 0, keys.length)];
    }
  }
}

function findPrevious(keys, prop, start, end) {
  // No previous key is available, so bail out
  if (start > end) return undefined;
  
  const middle = Math.floor((start + end) / 2);
  const current = keys[middle];
  const next = keys[middle + 1];
  
  // Previous property is found or is the maximum defined
  if (current < prop && (next > prop || next === undefined)) {
    return keys[middle];
  }
  
  // Otherwise, keep searching
  if (keys[middle] > prop) {
    return findPrevious(keys, prop, start, middle - 1);
  } else {
    return findPrevious(keys, prop, middle + 1, end);
  }
}
// Implement proxy
hash = new Proxy(hash, handler);

console.log(hash["00:01"]);  // undefined
console.log(hash["01:00"]);  // Hello
console.log(hash["01:01"]);  // Every  one
console.log(hash["01:04"]);  // Nice to meet you
console.log(hash["01:05"]);  // Nice to meet you
console.log(hash["01:10"]);  // Could you introduce yourself?
console.log(hash["01:17"]);  // Could you introduce yourself?
console.log(hash["01:19"]);  // Could you introduce yourself?
console.log(hash["01:22"]);  // Could you introduce yourself?
console.log(hash["01:23"]);  // Hi, My name is HashMap
console.log(hash["10:00"]);  // Hi, My name is HashMap

如果读取比写入更常见,您可以将Object.keys() 的结果存储在处理程序中并在每次插入时设置它,但这会使任何插入变为O(n) 并读取O(log(n))。您还需要在创建代理时定义键,否则它将只是一个空数组。

【讨论】:

  • 优秀:) 非常感谢。
  • 问题。 Proxy 有必要吗?因为我对此一无所知。
  • @jinongun 只有当你想让它看起来只是一个可以访问其属性的对象时才需要。在这种情况下,代理只是让您控制何时尝试访问属性。这类似于以对象作为参数调用函数(类似于findSameOrPrevious(hash, "00:00"),但接口更简单。
【解决方案3】:

我认为这正是您需要的,您将能够从哈希中检索,无需遍历哈希,它考虑了小时和分钟,因此您可以插入任何小时/分钟

const hash = {
  "00:00": "Hello",
  "00:01": "Every one",
  "00:04": "Nice to meet you",
  "00:10": "Could you introduce yourself?",
  "00:23": "Hi, My name is HashMap"
}


function gethrmin(key){
  ka=key.split(':')
  a=ka[0].charAt(0) ,b=ka[0].charAt(1), c=ka[1].charAt(0), d=ka[1].charAt(1) ,prev=""
  h= a =='0' && b=='0'?0:(a=='0' && b!='0'?parseInt(b):parseInt(ka[0])) 
  m= c =='0' && d=='0'?0:(c=='0' && d!='0'?parseInt(d):parseInt(ka[1]))
}
function prevTi(){
  return h<9&&h!=0 && m==0?prev="0"+`${h-1}`+":"+"59":( h>9 && m==0?prev=`${h-1}`+":"+"59":(h==0 && m==0?prev="23:59":(h==0 && m<9 &&m!=0?prev="00:"+"0"+`${m-1}`:(h==0 && m>9 &&m!=0?prev="00:"+`${m-1}`:(h<9 && h!=0 || m<9&& m!=0 ?prev="0"+h+":"+"0"+`${m-1}`:(h>9 && h!=0 || m>9 && m!=0 ?prev=h+':'+`${m-1}`:(h>9 && h!=0 || m<9 && m!=0 ?prev=h+':'+"0"+":"+`${m-1}`:(h<9 && h!=0 || m>9 && m!=0 ?prev="0"+h+':'+m:null))))))))
 }
function checkdb(key){
  if(!hash[key]){
    gethrmin(key)
    nk=prevTi()
   return checkdb(nk)
}
else
  return hash[key]
}
function _(key){
  if(hash[key]) return hash[key]
    return checkdb(key)

}
console.log(_('00:00'))
console.log(_('00:01'))
console.log(_('00:04'))
console.log(_('00:05'))
console.log(_('00:10'))
console.log(_('00:17'))
console.log(_('00:19'))
console.log(_('00:22'))
console.log(_('22:22'))

【讨论】:

    猜你喜欢
    • 2015-06-02
    • 2021-04-14
    • 1970-01-01
    • 2012-03-07
    • 2015-06-11
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    相关资源
    最近更新 更多