【问题标题】:Pick random value from JSON property从 JSON 属性中选择随机值
【发布时间】:2020-08-08 20:30:14
【问题描述】:

我有一个我在标题中描述的任务。我绝不能在我的代码中的某处使用数组、循环和 Object.keys。我只能使用 Math.random。

JSON 文件:

{
  "key": "item 1, item 2, item 3",
  "key2": "abc",
  "key3": "123"
}

如果没有我所描述的技术,我什至无法想象如何做到这一点。如果任务支持 Object.keys 这将非常简单(但我不能把它写成答案)。

我可以从 JSON 接收的对象:

let obj = {
           key: "item 1, item 2, item 3",
           key2: "abc",
           key3: "123"
       };

我用 Object.keys 选择随机值的函数(我不能使用):

 let randomProperty = function (obj) { 
 let keys = Object.keys(obj);    
 return obj[keys[ keys.length * Math.random() << 0]]; 
};

可以使用JSON.stringify和parse,因为它必须是JSON文件而不是我写的对象。

请帮忙!

【问题讨论】:

  • 家庭作业的任意限制使其不适合 SO。
  • 你可以使用 Object.entries 或 Object.values 吗?
  • 我不能使用 Object.entries 或 Object.values 或像 for in 这样的循环。禁用数组和循环的任何工作。
  • 当你说 cycles 时,你真的是指 loops 吗?
  • 是任意结构的键还是它们总是遵循key${someInt}的模式?

标签: javascript json random


【解决方案1】:

Ivan 的答案变体,代码少得多。 Stringify replacer 第一次计算参数,然后第二次选择一个。

let obj = {
  key: "item 1, item 2, item 3",
  key2: "abc",
  key3: "123"
};

let k, n = 0;
JSON.stringify(obj, (key, value) => (key && ++n || value));
n *= Math.random();
JSON.stringify(obj, (key, value) => (key && --n | 0 || (k = key) || value));
console.log(obj[k]);

【讨论】:

  • 全面披露:我觉得这毫无意义,但有点有趣。
  • 注意:这将正确处理["1", "2", "3"] 的值,而我的回答不会。我会接受这个答案。
  • 嵌套对象呢? AFAIR,我们会在transformer中获取它们的key,但我们不应该根据问题描述来选择它们。
  • @IvanKoshelev,我承认这个条件很难理解,但是如果你检查它,你会发现它只返回 value 如果键是假的(记得根对象是以空字符串作为其键进行处理),因此它仅扩展根对象以进行序列化。嵌套对象在技术上将被序列化为它们的键——尽管序列化的结果被丢弃,所以无论如何都没关系。我们实际上只是在使用JSON.stringify作弊,并利用其识别键和循环的能力。
  • @Wyck 好的,我现在看到了。
【解决方案2】:

使用JSON.stringify 将对象转换为字符串。然后,目标是将split 仅将键和值放入一个数组中,我们可以使用该数组并摆脱其他所有内容。使用slice 去掉前面的{ 和后面的}。通过replacing 用一些唯一的字符串(在我的示例中为“DELIM”)去除冒号和逗号,然后用该字符串split 来得到我们的数组。

一旦完成,我们只需要选择一个随机的odd索引,它会指向一个值。为此,请使用 Math.floor(Math.random() * (keysAndValuesArray.length / 2)) 从 0 到小于数组一半的 1 中选择一个数字(请记住,Math.random() 永远不会完全返回 1,Math.floor() 会将结果降低,而不是提高)。然后,我们将该数字乘以 2 得到一个随机偶数,该偶数指向我们数组中的一个键,然后加 1 得到我们的随机奇数指向我们数组中的一个值。

之后,剩下的就是从我们在我们选择的索引处创建的数组中获取值,然后通过JSON.parse 获取原始值。

请注意,这不是一个完美的解决方案,因为对象中包含我们尝试分割的字符串(":",")的值可能会导致问题发生。

var obj = {
  key: "item 1, item 2, item 3",
  key2: "abc",
  key3: 123
};

var keysAndValuesArray = JSON.stringify(obj).slice(1, -1).replace(/":/g, "\"DELIM").replace(/","/g, "\"DELIM\"").split("DELIM");
var randomOddIndex = Math.floor(Math.random() * (keysAndValuesArray.length / 2)) * 2 + 1;
console.log(keysAndValuesArray[randomOddIndex]);

【讨论】:

    【解决方案3】:

    这是否违反了任何规则集?

    更新 使其不按要求使用方括号。您还可以使用内置的 JS Map 及其 .get.set 方法。 附言我不确定是谁给你这个任务,但它在正常的 JS 课程中绝对没有位置。

    let obj = {
        key: "item 1, item 2, item 3",
        key2: "abc",
        key3: "123"
    };
    
    function get(obj, key) {
        // JS runtime can compile functions on the fly.
        // This allows to access keys with names known at runtime without square brackets
        const getter = new Function('x', `return x.${key}`);
        return getter(obj);
    }
    
    function set(obj, key, value) {
        const setter = new Function('x', 'y', `return x.${key} = y;`);
        setter(obj, value);
    }
    
    let count = 0;
    let indexToKeysDict = {};
    JSON.stringify(obj, function (key, val) {
        if (key && this === obj) {
            // keys can't start with number, so we add 'a' 
            set(indexToKeysDict, `a${count}`, key);
            count++;
        }
        return val;
    });
    
    console.log(`Array.isArray(indexToKeysDict) = ${Array.isArray(indexToKeysDict)}`); // to avoid any question about using arrays
    
    function getRandomInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
    }
    
    const index = getRandomInt(0, count);
    const key = get(indexToKeysDict, `a${index}`);
    console.log(get(obj, key));
    

    【讨论】:

    • 这行得通,但即使是数组中的方括号也无法设置。我还需要像这样解析类似的 JSON 文件,因为最初的任务听起来像“将 JSON 传输到没有“数组、循环、Object.keys”的对象中。
    • 是否允许JSON.parse
    • JSON.parse 允许
    • 所以这现在变成了一场隐藏循环的卑鄙的 js 竞赛?
    • @Bergi 或者我们正在帮助某人绕过基于正则表达式的天真系统来清理可提交的 JS 代码;-}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2015-07-15
    相关资源
    最近更新 更多